home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacGambit 2.0 / sources1 / Runtime (.c & .h) / os_mac_eEdit.c < prev    next >
Encoding:
Text File  |  1993-01-25  |  85.9 KB  |  2,674 lines  |  [TEXT/KAHL]

  1. /* os_mac_eEdit.c 
  2.  * 8Apr92  e
  3.  */
  4.  
  5. #include <MacHeaders>
  6.  
  7. #include "os_mac_eEdit.h"
  8.  
  9. /* an editor for text files by e
  10.    questions/comments via Internet <e@Flavors.COM> */
  11. /* Copyright © e, 1992. All rights reserved.
  12.     Developed using THINK C 5.0.1 for use with Gambit Scheme.
  13.     This code may be freely distributed as long as this notice remains.
  14.    based upon CEditor.C...
  15.     Copyright © BRH Toolsmith, 1992. All rights reserved.
  16.     Developed using THINK C 4.0.2 and Symantec's OOP libraries.
  17.     Portions of this codend )
  18.   { c = *p++;
  19.     if ( c < ' ' )
  20.     { if ( c == '\r' )
  21.       { line_count++;
  22.         *q++ = c;
  23.         start = q;
  24.       }
  25.       else if ( c == '\t' )
  26.       { c = tabstop - ( ( q - start ) % tabstop);
  27.         *q++ = c;
  28.         c -= 1;
  29.         start -= c;
  30.         new_size += c;
  31.       }
  32.       else if ( p == end )
  33.       {  *q++ = lastch; /* the last char may be a control char */
  34.       }
  35.       else
  36.       { old_size -= 1;
  37.         new_size -= 1;
  38.       }
  39.     }
  40.     else
  41.       *q++ = c;
  42.   }
  43.   *count = line_count;
  44.   *size = new_size;
  45.   SetHandleSize( h, new_size );
  46.   asm { move.w D0, error }         /* error = MemError(); */
  47.   if ( error == noErr )
  48.   { end = *(unsigned char **)h;
  49.     p = &end[new_size];
  50.     *--p = lastch;
  51.     start = &end[old_size-1];
  52.     while ( p > end )
  53.     { c = *--start;
  54.       if ( c < ' ' && c != '\r' )
  55.         while ( c-- ) *--p = ' ';
  56.       else
  57.         *--p = c;
  58.     }
  59.   }
  60.   else
  61.   { /* cleanup the buffer? */
  62.   }
  63.   return error;
  64. }
  65.  
  66. static void undoBugNi( eRec **hE )
  67. {    SysBeep(3); SysBeep(10); SysBeep(3);
  68. }
  69.  
  70. void eTeInit( void )
  71. {
  72.     gUtilRgn = NewRgn();
  73.     gClicks = 0;
  74.     /* 13Aug92  e  */
  75.     eTeScrap = NewHandle(0);
  76.     eTeScrapLen = 0;
  77.     eTeScrapCnt = (InfoScrap())->scrapCount - 1;
  78.     eTeGetScrap();
  79.     /* */
  80.     eTeUndoStuff.undoProc = undoBugNi;
  81.     eTeUndoStuff.undoTitle = utUndo;
  82.     eTeUndoStuff.undoText = NewHandle(0);
  83.     eTeUndoStuff.undoTeRec = NULL;
  84. }
  85.  
  86. /* replacement can be installed via eTeSetWordBreak() */
  87.  
  88. #if 0
  89. static long WordLimits( char *text, long offset, Boolean reverse )
  90. {
  91.     register char *ptr, c;
  92.  
  93.     ptr = text + offset;
  94.     if ( reverse ) {
  95.         /* Scan backwards until we find beginning of word */
  96.         while ( ptr > text ) {
  97.             c = *( ptr - 1 );
  98.             if ( ( c >= 'a' && c <= 'z' ) ||
  99.                  ( c >= 'A' && c <= 'Z' ) || 
  100.                  ( c >= '0' && c <= '9' ) || 
  101.                  ( c == '_' ) )
  102.                 --ptr;
  103.             else
  104.                 break;
  105.         }
  106.     }
  107.     else {
  108.         /* Scan forwards until we find end of word */
  109.         while ( 1 ) {
  110.             c = *ptr;
  111.             if ( ( c >= 'a' && c <= 'z' ) ||
  112.                  ( c >= 'A' && c <= 'Z' ) || 
  113.                  ( c >= '0' && c <= '9' ) || 
  114.                  ( c == '_' ) )
  115.                 ++ptr;
  116.             else
  117.                 break;
  118.         }
  119.     }
  120.     return( ptr - text );
  121. }
  122. #else
  123. static long WordLimits( char *text, long offset, Boolean reverse )
  124. {
  125.     register char *ptr, c;
  126.  
  127.     ptr = text + offset;
  128.     if ( reverse ) {
  129.         /* Scan backwards until we find beginning of word */
  130.         while ( ptr > text ) {
  131.             c = *( ptr - 1 );
  132.             if ( !( ( c >= 0 && c <= 32 ) ||
  133.                     ( c == '(' ) || ( c == ')' ) ||
  134.                     ( c == ';' ) || ( c == '"' ) ) )
  135.                 --ptr;
  136.             else
  137.                 break;
  138.         }
  139.     }
  140.     else {
  141.         /* Scan forwards until we find end of word */
  142.         while ( 1 ) {
  143.             c = *ptr;
  144.             if ( !( ( c >= 0 && c <= 32 ) ||
  145.                     ( c == '(' ) || ( c == ')' ) ||
  146.                     ( c == ';' ) || ( c == '"' ) ) )
  147.                 ++ptr;
  148.             else
  149.                 break;
  150.         }
  151.     }
  152.     return( ptr - text );
  153. }
  154. #endif
  155.  
  156. static short eTeNewRuns( eRec **hE, long len )
  157. {    register long *runPtr;
  158.     register eRec *pE;
  159.     short error;
  160.  
  161.     if ( (**hE).hRuns )
  162.         DisposHandle( (Handle )(**hE).hRuns );
  163.     (**hE).hRuns = (long **)NewHandle( MIN_RUNS * sizeof( long ) );
  164.       asm { move.w D0, error }         /* error = MemError(); */
  165.       if( error == noErr )
  166.       {    pE = *hE;
  167.         runPtr = *((*pE).hRuns);
  168.         *runPtr++ = 0L;
  169.         *runPtr = len;
  170.         (*pE).runsAllocated = MIN_RUNS;
  171.         (*pE).qRuns = 1;
  172.         (*pE).fustStyle = 0;
  173.     }
  174.     return error;
  175. }
  176.  
  177. long eTeTextLength( eRec **hE )
  178. {
  179.     return (*(**hE).hRuns)[(**hE).qRuns];
  180. }
  181.  
  182. eRec **eTeNew( WindowPtr macPort, Rect viewRect, short tabStops, short wrap,
  183.                  short autoInd, ControlHandle aHSizing, ControlHandle aVSizing )
  184. {    
  185.     register eRec *pE;
  186.     LineRec *linePtr;
  187.     eRec   **hE = (eRec **)NewHandle( sizeof( eRec ) );
  188.  
  189.     if( hE != 0 )
  190.     {    HLock( (Handle )hE );
  191.         pE = *hE;
  192.         (*pE).active = FALSE;
  193.         (*pE).macPort = macPort;
  194.         (*pE).viewRect = viewRect;
  195.         (*pE).width = viewRect.right - viewRect.left;
  196.         (*pE).height = viewRect.bottom - viewRect.top;
  197.         (*pE).hOrigin = -viewRect.left;
  198.         (*pE).vOrigin = -viewRect.top;
  199.         (*pE).position.h = (*pE).position.v = 0;
  200.         (*pE).hScale = (*pE).vScale = 1;
  201.         (*pE).bounds.v = 1;
  202.         (*pE).bounds.h = 1;     /* arbitrary size for now */
  203.         (*pE).leftMargin = 1;    /* room for cursor will blink at the far left */
  204.         (*pE).topMargin = 0;
  205.         (*pE).selStart.h = (*pE).selStart.v = 0;
  206.         (*pE).selEnd = (*pE).selStart;
  207.         (*pE).selActive = FALSE;
  208.         (*pE).caretChPos.h = (*pE).caretChPos.v = 0;
  209.         (*pE).writeChPos.h = (*pE).writeChPos.v = 0;
  210.         (*pE).caretState = CARET_OFF;
  211.         (*pE).maxRight = 0;
  212.         (*pE).eTeWordBreak = WordLimits;
  213.         SetPort( macPort );
  214.         (*pE).tabStops = tabStops;
  215.         (*pE).spaceWidth = 1;
  216.         (*pE).wrap = wrap;                            /*  5Jul92  e  */
  217.         (*pE).autoInd = autoInd;
  218.         (*pE).hText = NewHandle( 1L );
  219.         **((*pE).hText) = '\0';
  220.         (*pE).hLines = (LineRec **)NewHandle( MIN_LINES * sizeof( LineRec ) );
  221.         linePtr = *((*pE).hLines);
  222.         *linePtr++ = 0L;
  223.         *linePtr = 0L;
  224.         (*pE).linesAllocated = MIN_LINES;
  225.         /* 2May92  e  */
  226.         (*pE).hRuns = NULL;
  227.         eTeNewRuns( hE, 0L);
  228.         (*pE).qRuns = 0;
  229.         (*pE).hPrint = NULL;                        /* 28Sep92  e  */
  230.         /* scrollPane */
  231.         (*pE).hStep = (*pE).vStep = 1;
  232.         (*pE).hOverlap = (*pE).vOverlap = 1;
  233.         (*pE).hContext = (*pE).vContext = CONTEXT_LINES;
  234.         if ( ( (*pE).hSBar = aHSizing ) != NULL )
  235.         {    SetCRefCon( aHSizing, (long )hE );
  236.             SetCtlAction( aHSizing, hSBarActionProc );
  237.             /* SetThumbFunc( aHSizing, SBarThumbFunc ); */
  238.         }
  239.         if ( ( (*pE).vSBar = aVSizing ) != NULL )
  240.         {    SetCRefCon( aVSizing, (long )hE );
  241.             SetCtlAction( aVSizing, vSBarActionProc );
  242.             /* SetThumbFunc( aVSizing, SBarThumbFunc ); */
  243.         }
  244.         HUnlock( (Handle )hE );
  245.         eTeSetStyles( hE, &dfltStylNormal, &dfltStylHilite);
  246.         eTeAdjustScrollMax( hE );
  247.         eTeCalibrate( hE );
  248.         (**hE).dirty = FALSE;  /* was (*pE). 14Jul92  e  */
  249.         (**hE).active = TRUE;  /* was (*pE). 14Jul92  e  */
  250.     }
  251.     return hE;
  252. }
  253.  
  254. void eTeDispose( eRec **hE )
  255. {
  256.     if ( (**hE).hText )
  257.         DisposHandle( (**hE).hText );
  258.     (**hE).hText = NULL;
  259.     if ( (**hE).hLines )
  260.         DisposHandle( (Handle )(**hE).hLines );
  261.     (**hE).hLines = NULL;
  262.     if ( (**hE).hRuns )
  263.         DisposHandle( (Handle )(**hE).hRuns );
  264.     (**hE).hRuns = NULL;
  265.     if ( (**hE).hPrint )
  266.         DisposHandle( (Handle)(**hE).hPrint );    /*  28Sep92  e  */
  267.     DisposHandle( (Handle )hE );
  268. }
  269.  
  270. static void eTePrepare( eRec **hE )
  271. {
  272.     Rect        tempRect;                /* ClipRect may move memory    */
  273.  
  274.     SetPort( (**hE).macPort );
  275.     tempRect = (**hE).viewRect;
  276.     ClipRect(&tempRect);
  277.     /* obsolete...
  278.     TextFont( (**hE).fontNumber );
  279.     TextSize( (**hE).fontSize );
  280.     TextFace( 0 ); */
  281.     /* Paranoid... */
  282.     TextMode( srcOr );
  283. }
  284.  
  285. static void eTePrepareStyle( eRec **hE, short style )
  286. {
  287.   if( (**hE).curStyle != style )
  288.   { (**hE).curStyle = style;
  289.     TextFont( (**hE).style[style].tsFont );
  290.     TextFace( (**hE).style[style].tsFace );
  291.     TextSize( (**hE).style[style].tsSize );
  292.     /* RGBColor tsColor; */
  293.   }
  294. }
  295.  
  296. static void eTePrepareRun( eRec **hE, short run )
  297. {
  298.     eTePrepareStyle( hE, eTeRunToStyle( hE, run ) );
  299. }
  300.  
  301. static void eTeRefresh( eRec **hE )
  302. {
  303.     SetPort( (**hE).macPort );
  304.     InvalRect( &(**hE).viewRect );
  305. }
  306.  
  307. static void eTeUpdateCaretRect( eRec **hE )
  308. {
  309.     Point    tempPt;
  310.     register eRec    *pE;
  311.  
  312.     tempPt = eTeChPosToPoint( hE, (**hE).caretChPos );
  313.     pE = *hE;
  314.     (*pE).caretRect.top    = tempPt.v;
  315.     (*pE).caretRect.right  = tempPt.h;
  316.     (*pE).caretRect.left   = tempPt.h - 1;
  317.     (*pE).caretRect.bottom = tempPt.v + (*pE).caretHeight;
  318. }
  319.  
  320. void eTeSetWrap( eRec **hE, short wrap )
  321. {
  322.     /* 22Jul92  e  -- added limits */
  323.     if( wrap < 1 ) wrap = 1;
  324.     else if( wrap > 999 ) wrap = 999;
  325.     /* (**hE).wrap = wrap; */
  326.     /* 10Aug92  e   need to fix all ChPos for new wrap! */
  327.     if( (**hE).wrap != wrap )
  328.     { long car = eTeChPosToOffset( hE, (**hE).caretChPos );
  329.       long sta = eTeChPosToOffset( hE, (**hE).selStart );
  330.       long end = eTeChPosToOffset( hE, (**hE).selEnd );
  331.       long wri = eTeChPosToOffset( hE, (**hE).writeChPos );
  332.       (**hE).wrap = wrap;
  333.       eTeUpdateLineStarts( hE, 0 );
  334.       (**hE).caretChPos = eTeOffsetToChPos( hE, car );
  335.       (**hE).selStart   = eTeOffsetToChPos( hE, sta );
  336.       (**hE).selEnd     = eTeOffsetToChPos( hE, end );
  337.       (**hE).writeChPos = eTeOffsetToChPos( hE, wri );
  338.       eTeUpdateCaretRect( hE );
  339.       eTeRefresh( hE );
  340.     }
  341. }
  342.  
  343. void eTeSetTabStop( eRec **hE, short aTabStop )
  344. {
  345.     /* Undo? */
  346.     (**hE).tabStops = aTabStop;
  347.     (**hE).tabWidth = aTabStop * (**hE).spaceWidth;
  348.     eTeRefresh( hE );
  349. }
  350.  
  351. static short eTeTabStop( eRec **hE, register short curPosition )
  352. {
  353.     register short tabWidth = (**hE).tabWidth;
  354.     return (curPosition +
  355.              (tabWidth -
  356.                ((curPosition - (**hE).leftMargin + (**hE).hOrigin) % tabWidth)));
  357. }
  358.  
  359. void eTeSetWordBreak( eRec **hE, ProcPtr aFunc )
  360. {
  361.     if ( aFunc == NULL )
  362.         (**hE).eTeWordBreak = WordLimits;
  363.     else
  364.         (**hE).eTeWordBreak = aFunc;
  365. }
  366.  
  367. /* 23Jul92  e  */
  368.  
  369. /* Inverts the text between the start and stop positions. */
  370.  
  371. static void eTeHiliteRange( eRec **hE, register ChPos start, register ChPos stop )
  372. {
  373.     Rect tmpRect;
  374.     Point stopPt;
  375.     register short vScale;
  376.     
  377.     if ( ! (**hE).active )
  378.         return;
  379.  
  380.     topLeft( tmpRect ) = eTeChPosToPoint( hE, start );
  381.     tmpRect.left -= 1;
  382.  
  383.     vScale = (**hE).vScale;
  384.  
  385.     /* Just need to hilite within same line */
  386.     if ( start.v == stop.v ) {
  387.         botRight( tmpRect ) = eTeChPosToPoint( hE, stop );
  388.         tmpRect.right -= 1;
  389.         tmpRect.bottom = tmpRect.top + vScale;
  390.         if ( tmpRect.left != tmpRect.right ) {
  391.             eTePrepare( hE );
  392.             asm { bclr #hiliteBit, HiliteMode }
  393.             InvertRect( &tmpRect );
  394.         }
  395.     }
  396.     /* Hilite spans more than one line */
  397.     else
  398.     {    stopPt = eTeChPosToPoint( hE, stop );
  399.         if( tmpRect.top < (**hE).viewRect.bottom && stopPt.v >= (**hE).viewRect.top )
  400.         {    eTePrepare( hE );
  401.             tmpRect.right = (**hE).viewRect.right;
  402.             tmpRect.bottom = tmpRect.top + vScale;
  403.             if( tmpRect.bottom > (**hE).viewRect.top )
  404.             {    asm { bclr #hiliteBit, HiliteMode }
  405.                 InvertRect( &tmpRect );
  406.                 tmpRect.top += vScale;
  407.             }
  408.             else
  409.                 tmpRect.top = (**hE).viewRect.top;
  410.             tmpRect.left = (**hE).viewRect.left;
  411.             tmpRect.bottom = Min( stopPt.v, (**hE).viewRect.bottom );
  412.             asm { bclr #hiliteBit, HiliteMode }
  413.             InvertRect( &tmpRect );
  414.             if( stopPt.v < (**hE).viewRect.bottom )
  415.             {    tmpRect.bottom += vScale;
  416.                 tmpRect.top = stopPt.v;
  417.                 tmpRect.right = stopPt.h - 1;
  418.                 asm { bclr #hiliteBit, HiliteMode }
  419.                 InvertRect( &tmpRect );
  420.             }
  421.         }
  422.     }
  423. }
  424.  
  425. /* 23Jul92  e  */
  426.  
  427. static void eTeSetCaretState( eRec **hE, Boolean state )
  428. {
  429.     Rect    tmpRect;
  430.     register eRec    *pE = *hE;
  431.  
  432.     if (   ! (*pE).selActive
  433.           && (*pE).active
  434.           && (*pE).caretState != state )
  435.     {
  436.         (*pE).caretState = state;
  437.         tmpRect = (*pE).caretRect;
  438.         eTePrepare( hE );
  439.         PenMode(patXor);
  440.         FrameRect( &tmpRect );
  441.         PenNormal();
  442.     }
  443. }
  444.  
  445. void eTeActivate( eRec **hE )
  446. {
  447.     if( (**hE).active == FALSE )
  448.     {    (**hE).active = TRUE;
  449.         if( (**hE).selActive )
  450.             eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );
  451.     }
  452. }
  453.  
  454. void eTeDeactivate( eRec **hE )
  455. {
  456.     if( (**hE).active == TRUE )
  457.     {    if( (**hE).selActive )
  458.             eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );
  459.         else
  460.             eTeSetCaretState( hE, CARET_OFF );
  461.         (**hE).active = FALSE;
  462.     }
  463. }
  464.  
  465. void eTeIdle( eRec **hE )
  466. {
  467.     static long lastCaretToggle = 0L;
  468.     register long    now;
  469.     Rect    tmpRect;
  470.  
  471.     gMaxSleep = GetCaretTime();    /* user may change it using desk accessory */
  472.     now = TickCount();
  473.     if ( now - lastCaretToggle >= gMaxSleep ) {
  474.         lastCaretToggle = now;
  475.         eTeSetCaretState( hE, (**hE).caretState == CARET_OFF ? CARET_ON : CARET_OFF );
  476.     }
  477.     else {
  478.         gMaxSleep -= ( now - lastCaretToggle );
  479.     }
  480. }
  481.  
  482. static void eTeResize( eRec **hE, register Rect *delta )
  483. {
  484.     register eRec *pE = *hE;
  485.  
  486.     (*pE).width      += delta->right - delta->left;
  487.     (*pE).height     += delta->bottom - delta->top;
  488.     (*pE).leftMargin += delta->left;
  489.     (*pE).topMargin  += delta->top;
  490.  
  491.     (*pE).hOrigin -= delta->left;
  492.     (*pE).vOrigin -= delta->top;
  493.  
  494.     eTeUpdateCaretRect( hE );
  495.     eTeAdjustScrollMax( hE );
  496.     eTeCalibrate( hE );
  497. }
  498.  
  499. void eTeNewView( eRec **hE, Rect *viewRect )
  500. {
  501.     register eRec *pE = *hE;
  502.     Rect    delta;
  503.     
  504.     delta = *viewRect;
  505.     delta.top -= (*pE).viewRect.top;
  506.     delta.left -= (*pE).viewRect.left;
  507.     delta.bottom -= (*pE).viewRect.bottom;
  508.     delta.right -= (*pE).viewRect.right;
  509.     (*pE).viewRect   = *viewRect;
  510.     
  511.     eTeResize( hE, &delta );
  512. }
  513.  
  514. /* eTeSetStyles also causes the display to be redrawn */
  515.  
  516. void eTeSetStyles( eRec **hE, TextStyle *ts0, TextStyle *ts1 )
  517. {
  518.     short        height[2];
  519.     FontInfo    fontInfo[2];
  520.     ChPos        tmpPt;
  521.     short        bigger;
  522.  
  523.     (**hE).style[0] = *ts0;
  524.     (**hE).style[1] = *ts1;
  525.     (**hE).curStyle = NOSTYLE;
  526.  
  527.     /* Turn off cursor */
  528.     eTePrepare( hE );
  529.     eTeSetCaretState( hE, CARET_OFF );
  530.  
  531.     eTePrepareStyle( hE, 1 );
  532.     GetFontInfo( &fontInfo[1] );
  533.     height[1] = CharWidth( OPTION_SPACE );
  534.  
  535.     eTePrepareStyle( hE, 0 );
  536.     GetFontInfo( &fontInfo[0] );
  537.     height[0] = CharWidth( OPTION_SPACE );
  538.     
  539.     (**hE).spaceWidth = Max ( height[0], height[1] );
  540.     /* calculate new tabstop based on new font/size */
  541.     (**hE).tabWidth = (**hE).tabStops * (**hE).spaceWidth;
  542.  
  543.     height[0] = fontInfo[0].ascent + fontInfo[0].descent;
  544.     height[1] = fontInfo[1].ascent + fontInfo[1].descent;
  545.     
  546.     bigger = height[1] > height[0] ? 1 : 0;
  547.     (**hE).fontAscent = fontInfo[bigger].ascent;
  548.     (**hE).caretHeight = height[bigger];
  549.  
  550.     /* Update caret values for new font */
  551.     eTeUpdateCaretRect( hE );
  552.     (**hE).maxRight = (**hE).caretRect.right;
  553.  
  554.     /*
  555.      * Set the scale values for our scrollbars. Vertical scrolling is done by 
  556.      * lines; horizontal by widest character. First, move to top of panorama (but
  557.      * don't redraw), then change the scale values. Finally, move back to original
  558.      * position and redraw screen.
  559.      */
  560.     tmpPt = (**hE).position;
  561.     eTeScroll( hE, -(**hE).position.h, -(**hE).position.v, FALSE );
  562.     (**hE).hScale = Max( fontInfo[0].widMax, fontInfo[1].widMax );
  563.     (**hE).vScale = (**hE).caretHeight + fontInfo[bigger].leading;
  564.     eTeAdjustScrollMax( hE );
  565.     eTeScrollTo( hE, tmpPt, FALSE );
  566.     eTeRefresh( hE );
  567. }
  568.  
  569. #ifdef include_obsolete_code
  570.  
  571. void eTeSetFontNumber( eRec **hE, short aFontNumber )
  572. {
  573.     Str255        fontName;
  574.  
  575.     GetFontName( aFontNumber, fontName );
  576.     if ( fontName[0] == 0 )
  577.         aFontNumber = 0;    /* If font does not exist, then use the system font */
  578.  
  579.     /* Undo? */
  580.     (**hE).fontNumber = aFontNumber;
  581.     eTeFontChanged( hE );
  582. }
  583.  
  584. void eTeSetFontName( eRec **hE, Str255 aFontName )
  585. {
  586.     short    fontNumber;
  587.  
  588.     GetFNum( aFontName, &fontNumber );
  589.     eTeSetFontNumber( hE, ( fontNumber > 0 ) ? fontNumber : 0 );
  590. }
  591.  
  592. void eTeSetFontSize( eRec **hE, short aFontSize )
  593. {
  594.     /* Undo? */
  595.     (**hE).fontSize = aFontSize;
  596.     eTeFontChanged( hE );
  597. }
  598.  
  599. #endif
  600.  
  601. /* static --  25Sep92  e  for os_mac_Print.c */
  602. void eTeDrawLine( eRec **hE, ChPos beginPos, Point location )
  603. {
  604.     register char    c, *charPtr, *firstChar;
  605.     register short    count;
  606.     long     offset, instyle, inline, eol;
  607.     short     run, style;
  608.     Point    pt;
  609.  
  610.     HLock( (**hE).hText );
  611.     MoveTo( location.h, location.v + (**hE).fontAscent );
  612.     
  613.     offset = *(*(**hE).hLines + beginPos.v) + beginPos.h;
  614.     charPtr = *(**hE).hText + offset;
  615.     eol    = *(*(**hE).hLines + beginPos.v + 1);
  616.     inline = eol - offset;
  617.     run = eTeOffsetToRun( hE, offset );
  618.     while( inline )
  619.     {    eTePrepareRun( hE, run );
  620.         instyle = (*(**hE).hRuns)[++run] - offset;
  621.         if( instyle > inline )
  622.             instyle = inline;
  623.         inline -= instyle;
  624.         offset += instyle;
  625.         firstChar = charPtr;
  626.         count = 0;
  627.         while ( instyle && ( c = *charPtr++ ) != RETURN )    /* 11Aug92  e   was: instyle-- */
  628.         {    if ( c == TAB ) 
  629.             {    if ( count > 0 ) DrawText( firstChar, 0, count );
  630.                 GetPen( &pt );
  631.                 pt.h = eTeTabStop( hE, pt.h );
  632.                 MoveTo( pt.h, pt.v );
  633.                 firstChar = charPtr;
  634.                 count = 0;
  635.             }
  636.             else ++count;
  637.             instyle -= 1;                                    /* 11Aug92  e  */
  638.         }
  639.         if ( count  > 0 ) DrawText( firstChar, 0, count );
  640.     }
  641.     if( c != RETURN && *charPtr != '\0' ) DrawChar( 0xd7 );
  642.     /* if( instyle == 0 && *charPtr != '\0' ) DrawChar( 0xd7 ); /* NG!? 11Aug92  e  */
  643.     HUnlock( (**hE).hText );
  644. }
  645.  
  646. void eTeDraw( eRec **hE, Rect *area )
  647. {
  648.     eRec *pE;
  649.     short    vFirst, vLast;
  650.     ChPos    startPos;
  651.     Point    location;
  652.     Rect    tRect;
  653.     Boolean doCaret;    /* 23Jul92  e */
  654.     
  655.     HLock( (Handle )hE );
  656.     pE = *hE;
  657.     
  658.     if ( SectRect( area, &(*pE).viewRect, &tRect ) )
  659.     {
  660.         eTePrepare( hE );
  661.         
  662.         doCaret = ( ( ! (*pE).selActive ) && ( (*pE).caretState == CARET_ON ) );
  663.         if( doCaret ) eTeSetCaretState( hE, CARET_OFF );
  664.  
  665.         vFirst = ( tRect.top - (*pE).topMargin + (*pE).vOrigin ) / (*pE).vScale;
  666.         vLast = ( tRect.bottom + (*pE).vScale - (*pE).topMargin + (*pE).vOrigin - 1 )
  667.                 / (*pE).vScale;
  668.  
  669.         if ( vFirst < 0 )
  670.             vFirst = 0;
  671.         if ( vLast >= (*pE).bounds.v ) 
  672.             vLast = (*pE).bounds.v - 1;
  673.  
  674.         EraseRect( &tRect );
  675.  
  676.         if ( vFirst < (*pE).bounds.v && vLast >= 0)
  677.  
  678.         {    location.h = (*pE).leftMargin - (*pE).hOrigin;
  679.             location.v = vFirst * (*pE).vScale + (*pE).topMargin - (*pE).vOrigin;
  680.             startPos.h = 0;
  681.  
  682.             for ( startPos.v = vFirst;
  683.                   startPos.v <= vLast;
  684.                   location.v += (*pE).vScale, ++startPos.v )
  685.             {    eTeDrawLine( hE, startPos, location );
  686.             }
  687.             if ( (*pE).selActive )
  688.                  eTeHiliteRange( hE, (*pE).selStart, (*pE).selEnd );    /* may have munged it */
  689.             else if( doCaret )
  690.                 eTeSetCaretState( hE, CARET_ON );
  691.         }
  692.     }
  693.     HUnlock( (Handle )hE );
  694. }
  695.  
  696. void eTeUpdate( eRec **hE )
  697. {
  698.     Rect tempRect;
  699.     
  700.     eTePrepare( hE );
  701.     tempRect = (**((**hE).macPort)->visRgn).rgnBBox;
  702.     eTeDraw( hE, &tempRect );
  703. }
  704.         
  705. #ifndef THINK_ARROWS
  706.  
  707. static void eTeExtSelGuts( eRec **hE, ChPos chPos )
  708. {
  709.     if( PTL( chPos ) < PTL( (**hE).caretChPos ) )
  710.     {    eTeHiliteRange( hE, chPos, (**hE).caretChPos );
  711.         if( PTL( (**hE).caretChPos ) == PTL( (**hE).selStart ) )
  712.             (**hE).selStart = chPos;
  713.         else if( PTL( chPos ) >= PTL( (**hE).selStart ) )
  714.             (**hE).selEnd = chPos;
  715.         else
  716.         {    (**hE).selEnd = (**hE).selStart;
  717.             (**hE).selStart = chPos;
  718.         }
  719.     }
  720.     else if( PTL( chPos ) > PTL( (**hE).caretChPos ) )
  721.     {    eTeHiliteRange( hE, (**hE).caretChPos, chPos );
  722.         if( PTL( (**hE).caretChPos ) == PTL( (**hE).selEnd ) )
  723.             (**hE).selEnd = chPos;
  724.         else if( PTL( chPos ) <= PTL( (**hE).selEnd ) )
  725.             (**hE).selStart = chPos;
  726.         else
  727.         {    (**hE).selStart = (**hE).selEnd;
  728.             (**hE).selEnd = chPos;
  729.         }
  730.     }
  731. }
  732.  
  733. #endif
  734.  
  735. static void eTeEnsureChPos( eRec **hE, ChPos chPos )
  736. {
  737.     if( PTL( chPos ) != PTL( (**hE).caretChPos ) )
  738.     {    (**hE).caretChPos = chPos;
  739.         eTeUpdateCaretRect( hE );
  740.         (**hE).maxRight = (**hE).caretRect.right;
  741.     }
  742. }
  743.  
  744. void eTeKey( eRec **hE, char theChar, Byte keyCode, short modifiers, short style )
  745. {
  746.     char        *charPtr;
  747.     LineRec        *linePtr;
  748.     long        offset;
  749.     short            eoln;
  750.     ChPos        chPos;
  751.     char        chars[ 255 ];
  752.     Boolean        shifted, optioned, commanded;
  753.     Rect         invalRect;
  754.     long        new;
  755.     Point         aPt;
  756.  
  757.     ObscureCursor();
  758.     eTeSetCaretState( hE, CARET_OFF ); /* move up here 22Jul92  e  */
  759.  
  760.     shifted = ( modifiers & shiftKey ) ? 1 : 0;
  761.     optioned = ( modifiers & optionKey ) ? 1 : 0;
  762.     commanded = ( modifiers & cmdKey ) ? 1 : 0;
  763.  
  764.     switch ( keyCode ) {
  765.         case KeyF1:
  766.             /* Undo */
  767.             break;
  768.         case KeyF2:
  769.             eTeCut( hE );
  770.             break;
  771.         case KeyF3:
  772.             eTeCopy( hE );
  773.             break;
  774.         case KeyF4:
  775.             /* eTePaste( hE, style );            /* correct        3May92  e */
  776.             eTePaste( hE, style ^ optioned );    /* for debugging  3May92  e */
  777.             break;
  778.         case KeyF5:
  779.         case KeyF6:
  780.         case KeyF7:
  781.         case KeyF8:
  782.         case KeyF9:
  783.         case KeyF10:
  784.         case KeyF11:
  785.         case KeyF12:
  786.         case KeyF13:
  787.         case KeyF14:
  788.         case KeyF15:
  789.             /* DoFunctionKey( theChar, keyCode, modifiers ); */
  790.             break;
  791.  
  792.         case KeyHome:                                            /*** HOME ***/
  793.             eTeScrollTo( hE, zeroPos, TRUE );
  794.             break;
  795.  
  796.         case KeyEnd:                                            /*** END ***/
  797.             chPos.v = (**hE).bounds.v - (**hE).vSpan;
  798.             if ( chPos.v < 0 )
  799.                 chPos.v = 0;
  800.             chPos.h = (**hE).position.h;
  801.             eTeScrollTo( hE, chPos, TRUE );
  802.             break;
  803.  
  804.         case KeyPageUp:                                            /*** PAGE UP ***/
  805.             eTeDoVscroll( hE, inPageUp );
  806.             eTeAdjustScrollMax( hE );
  807.             break;
  808.  
  809.         case KeyPageDown:                                        /*** PAGE DOWN ***/
  810.             eTeDoVscroll( hE, inPageDown );
  811.             eTeAdjustScrollMax( hE );
  812.             break;
  813.  
  814.         case KeyDel:                                            /*** DEL FWD ***/
  815.             offset = eTeChPosToOffset( hE, (**hE).caretChPos );
  816.             if ( (**hE).selActive )
  817.                 eTeDelete( hE );
  818.             else if ( optioned ) { /* delete to end of line */
  819.                 /* 5Jul92  e */
  820.                 chPos = (**hE).caretChPos;
  821.                 linePtr = *(**hE).hLines;
  822.               labelTryAgainK:
  823.                 chPos.h = linePtr[ chPos.v + 1 ] - linePtr[ chPos.v ];
  824.                 if ( chPos.v < (**hE).bounds.v - 1 )
  825.                 { --chPos.h;
  826.                   new = eTeChPosToOffset( hE, chPos );
  827.                   if( *(*(**hE).hText + new) != RETURN )
  828.                   { chPos.v++;
  829.                     goto labelTryAgainK;
  830.                   }
  831.                   if( new == offset )
  832.                       chPos.h++;    /* delete the RETURN if its all there is */
  833.                 }
  834.                 eTeKillTo( hE, chPos );
  835.             }
  836.             else if ( *(*(**hE).hText + offset) != '\0' ) {
  837.                 /* 14Aug92  e   for undo...
  838.                 eTeEdGuts( hE, EMPTY_PTR, 0L, *(*(**hE).hText + offset) == RETURN, TRUE, style );
  839.                 */
  840.                 eTeKillTo( hE, eTeOffsetToChPos( hE, offset + 1 ) ); /* optimize for Undo Typing */
  841.             }
  842.             break;
  843.  
  844.         default:
  845.             MoveHHi( (Handle )(**hE).hLines );
  846.             HLock( (Handle )(**hE).hLines );
  847.             /* eTeSetCaretState( hE, CARET_OFF );  --  move above  22Jul92  e  */
  848.             linePtr = *(**hE).hLines;
  849.             switch( theChar ) {
  850.                 case LEFT_ARROW:                                /*** LEFT ARROW ***/
  851.                     if ( (**hE).selActive && ! shifted )
  852.                     {    /* if no shift key and there is a selection, remove it */
  853.                         eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );
  854.                         chPos = (**hE).selEnd = (**hE).selStart;
  855.                     }
  856. #ifndef THINK_ARROWS
  857.                     else if( (**hE).selActive && optioned && commanded )
  858.                     {    /* move chPos to start of selection if not there */
  859.                         chPos = (**hE).selStart;
  860.                         eTeEnsureChPos( hE, chPos );
  861.                     }
  862. #endif
  863.                     else
  864.                     {    if ( shifted )
  865.                           {    if ( ! (**hE).selActive )
  866.                                 (**hE).selStart = (**hE).selEnd = (**hE).caretChPos;
  867. #ifdef THINK_ARROWS
  868.                             (**hE).caretChPos = (**hE).selStart;
  869. #endif
  870.                         }
  871.                         chPos = (**hE).caretChPos;
  872.                         if ( commanded )
  873.                         {    chPos.h = 0;    /* move to beginning of line */
  874.                             labelTryAgainL:    /* added the rest 5Jul92  e  */
  875.                             if ( chPos.v > 0 )
  876.                             {    offset = eTeChPosToOffset( hE, chPos );
  877.                                 if( *(*(**hE).hText + offset - 1) != RETURN )
  878.                                 {    chPos.v--;
  879.                                     goto labelTryAgainL;
  880.                                 }
  881.                             }
  882.                         }
  883.                         else if ( optioned )
  884.                         {                     /* move to start/end of previous word */
  885.                               offset = eTeChPosToOffset( hE, chPos );
  886.                             new = WordLimits( *(**hE).hText, offset, TRUE );
  887.                             if ( new == offset && offset != 0L )
  888.                                 --new;
  889.                             chPos = eTeOffsetToChPos( hE, new );
  890.                         }
  891.                           else                 /* move to previous character position */
  892.                             chPos = eTeOffsetToChPos( hE, eTeChPosToOffset( hE, chPos ) - 1 );
  893.                         if ( shifted )
  894.                         {
  895. #ifdef THINK_ARROWS
  896.                             eTeHiliteRange( hE, chPos, (**hE).selStart );
  897.                             (**hE).selStart = chPos;
  898. #else
  899.                             eTeExtSelGuts( hE, chPos );
  900. #endif
  901.                             /* 30Apr92  e  -- needed if newly active AND scrolling... */
  902.                             (**hE).selActive = ( PTL( (**hE).selStart ) != PTL( (**hE).selEnd ) );
  903.                         }
  904.                     }
  905.                     (**hE).caretChPos = chPos;
  906.                     eTeUpdateCaretRect( hE );
  907.                     (**hE).maxRight = (**hE).caretRect.right;
  908.                     eTeShowCaret( hE );
  909.                     break;
  910.  
  911.                 case RIGHT_ARROW:                                /*** RIGHT ARROW ***/
  912.                     if ( (**hE).selActive && ! shifted )
  913.                     {    /* if no shift key and there is a selection, remove it */
  914.                         eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );
  915.                         chPos = (**hE).selStart = (**hE).selEnd;
  916.                     }
  917. #ifndef THINK_ARROWS
  918.                     else if( (**hE).selActive && optioned && commanded )
  919.                     {    /* move chPos to end of selection if not there */
  920.                         chPos = (**hE).selEnd;
  921.                         eTeEnsureChPos( hE, chPos );
  922.                     }
  923. #endif
  924.                     else
  925.                     {    if ( shifted )
  926.                           {    if ( ! (**hE).selActive )
  927.                                 (**hE).selStart = (**hE).selEnd = (**hE).caretChPos;
  928. #ifdef THINK_ARROWS
  929.                             (**hE).caretChPos = (**hE).selEnd;
  930. #endif
  931.                         }
  932.                         chPos = (**hE).caretChPos;
  933.                         if ( commanded )
  934.                         {                    /* move to end of line */
  935.                             labelTryAgainR:
  936.                             chPos.h = linePtr[ chPos.v + 1 ] - linePtr[ chPos.v ];
  937.                             if ( chPos.v < (**hE).bounds.v - 1 )
  938.                             {    /* 5Jul92  e  was: --chPos.h; */
  939.                                 --chPos.h;
  940.                                 offset = eTeChPosToOffset( hE, chPos );
  941.                                 if( *(*(**hE).hText + offset) != RETURN )
  942.                                 {    chPos.v++;
  943.                                     goto labelTryAgainR;
  944.                                 }
  945.                             }
  946.                         }
  947.                         else if ( optioned )
  948.                         {                     /* move to start/end of next word */
  949.                               offset = eTeChPosToOffset( hE, chPos );
  950.                             new = WordLimits( *(**hE).hText, offset, FALSE );
  951.                             if ( new == offset && *(*(**hE).hText + offset) != '\0' )
  952.                                 ++new;
  953.                             chPos = eTeOffsetToChPos( hE, new );
  954.                         }
  955.                           else                 /* move to previous character position */
  956.                             chPos = eTeOffsetToChPos( hE, eTeChPosToOffset( hE, chPos ) + 1 );
  957.                         if ( shifted )
  958.                         {
  959. #ifdef THINK_ARROWS
  960.                             eTeHiliteRange( hE, (**hE).selEnd, chPos );
  961.                             (**hE).selEnd = chPos;
  962. #else
  963.                             eTeExtSelGuts( hE, chPos );
  964. #endif
  965.                             /* 30Apr92  e  -- needed if newly active AND scrolling... */
  966.                             (**hE).selActive = ( PTL( (**hE).selStart ) != PTL( (**hE).selEnd ) );
  967.                         }
  968.                     }
  969.                     (**hE).caretChPos = chPos;
  970.                     eTeUpdateCaretRect( hE );
  971.                     (**hE).maxRight = (**hE).caretRect.right;
  972.                     eTeShowCaret( hE );
  973.                     break;
  974.  
  975.                 case UP_ARROW:                                /*** UP ARROW ***/
  976.                     if ( (**hE).selActive && ! shifted )
  977.                     {    /* if no shift key and there is a selection, remove it */
  978.                         eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );
  979.                         chPos = (**hE).selEnd = (**hE).selStart;
  980.                     }
  981. #ifndef THINK_ARROWS
  982.                     else if( (**hE).selActive && optioned && commanded )
  983.                     {    /* move chPos to start of selection if not there */
  984.                         chPos = (**hE).selStart;
  985.                         eTeEnsureChPos( hE, chPos );
  986.                     }
  987. #endif
  988.                     else
  989.                     {    if ( shifted )
  990.                           {    if ( ! (**hE).selActive )
  991.                                 (**hE).selStart = (**hE).selEnd = (**hE).caretChPos;
  992. #ifdef THINK_ARROWS
  993.                             else
  994.                                 eTeEnsureChPos( hE, (**hE).selStart );
  995. #endif
  996.                         }
  997.                         chPos = (**hE).caretChPos;
  998.                         if ( commanded )
  999.                             chPos.h = chPos.v = 0;    /* move to beginning of text */
  1000.                         else if( optioned )
  1001.                         {    aPt.h = (**hE).maxRight;
  1002.                             chPos.v -= (**hE).vSpan - (**hE).vOverlap;    /* move up one page */
  1003.                             if( chPos.v < 0 ) chPos.v = 0;
  1004.                             chPos = eTePointHtoChPosH( hE, aPt, chPos );
  1005.                         }
  1006.                           else if ( chPos.v > 0 )
  1007.                         {    /* NG...   [caretRect.top can be bogus!]
  1008.                             aPt.h = (**hE).maxRight;
  1009.                             aPt.v = (**hE).caretRect.top - (**hE).vScale;
  1010.                             chPos = eTePointToChPos( hE, aPt );
  1011.                             */
  1012.                             aPt.h = (**hE).maxRight;
  1013.                             chPos.v -= 1;    /* move up one line */
  1014.                             chPos = eTePointHtoChPosH( hE, aPt, chPos );
  1015.                         }
  1016.                         if ( shifted )
  1017.                         {
  1018. #ifdef THINK_ARROWS
  1019.                             eTeHiliteRange( hE, chPos, (**hE).selStart );
  1020.                             (**hE).selStart = chPos;
  1021. #else
  1022.                             eTeExtSelGuts( hE, chPos );
  1023. #endif
  1024.                             /* 30Apr92  e  -- needed if newly active AND scrolling... */
  1025.                             (**hE).selActive = ( PTL( (**hE).selStart ) != PTL( (**hE).selEnd ) );
  1026.                         }
  1027.                     }
  1028.                     (**hE).caretChPos = chPos;
  1029.                     eTeUpdateCaretRect( hE );
  1030.                     eTeShowCaret( hE );
  1031.                     break;
  1032.  
  1033.                 case DOWN_ARROW:                            /*** DOWN ARROW ***/
  1034.                     if ( (**hE).selActive && ! shifted )
  1035.                     {    /* if no shift key and there is a selection, remove it */
  1036.                         eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );
  1037.                         chPos = (**hE).selStart = (**hE).selEnd;
  1038.                     }
  1039. #ifndef THINK_ARROWS
  1040.                     else if( (**hE).selActive && optioned && commanded )
  1041.                     {    /* move chPos to end of selection if not there */
  1042.                         chPos = (**hE).selEnd;
  1043.                         eTeEnsureChPos( hE, chPos );
  1044.                     }
  1045. #endif
  1046.                     else
  1047.                     {    if ( shifted )
  1048.                           {    if ( ! (**hE).selActive )
  1049.                                 (**hE).selStart = (**hE).selEnd = (**hE).caretChPos;
  1050. #ifdef THINK_ARROWS
  1051.                             else
  1052.                                 eTeEnsureChPos( hE, (**hE).selEnd );
  1053. #endif
  1054.                         }
  1055.                         chPos = (**hE).caretChPos;
  1056.                         if ( commanded )
  1057.                         {                    /* move to end of text */
  1058.                             chPos.v = (**hE).bounds.v - 1;
  1059.                             chPos.h = linePtr[ chPos.v + 1 ] - linePtr[ chPos.v ];
  1060.                         }
  1061.                         else if( optioned )
  1062.                         {    aPt.h = (**hE).maxRight;
  1063.                             if( chPos.v > (**hE).bounds.v - (**hE).vSpan + (**hE).vOverlap )
  1064.                                 chPos.v = (**hE).bounds.v - 1;
  1065.                             else
  1066.                                 chPos.v += (**hE).vSpan - (**hE).vOverlap;    /* move down one page */
  1067.                             chPos = eTePointHtoChPosH( hE, aPt, chPos );
  1068.                         }
  1069.                           else if ( chPos.v < (**hE).bounds.v - 1 )
  1070.                         {    /* NG...   [caretRect.top can be bogus!]
  1071.                             aPt.h = (**hE).maxRight;
  1072.                             aPt.v = (**hE).caretRect.top + (**hE).vScale;
  1073.                             chPos = eTePointToChPos( hE, aPt );
  1074.                             */
  1075.                             aPt.h = (**hE).maxRight;
  1076.                             chPos.v += 1;    /* move down one line */
  1077.                             chPos = eTePointHtoChPosH( hE, aPt, chPos );
  1078.                         }
  1079.                         if ( shifted )
  1080.                         {
  1081. #ifdef THINK_ARROWS
  1082.                             eTeHiliteRange( hE, (**hE).selEnd, chPos );
  1083.                             (**hE).selEnd = chPos;
  1084. #else
  1085.                             eTeExtSelGuts( hE, chPos );
  1086. #endif
  1087.                             /* 30Apr92  e  -- needed if newly active AND scrolling... */
  1088.                             (**hE).selActive = ( PTL( (**hE).selStart ) != PTL( (**hE).selEnd ) );
  1089.                         }
  1090.                     }
  1091.                     (**hE).caretChPos = chPos;
  1092.                     eTeUpdateCaretRect( hE );
  1093.                     eTeShowCaret( hE );
  1094.                     break;
  1095.  
  1096.                 case DELETE:                                /*** DELETE ***/
  1097.                     eTeDelete( hE );
  1098.                     break;
  1099.  
  1100.                 default:                                    /*** TEXT ***/
  1101.                     /* Undo? */
  1102.                     if ( theChar == ENTER || theChar == RETURN ) {
  1103.                         chars[ 0 ] = RETURN;
  1104.                         offset = 1;
  1105. #ifdef THINK_RETURN
  1106.                         if ( (**hE).caretChPos.v > 0 ) {
  1107.                             charPtr = *(**hE).hText + linePtr[ (**hE).caretChPos.v - 1 ];
  1108.                             while ( *charPtr == TAB || *charPtr == SPACE ) {
  1109.                                 chars[ offset++ ] = *charPtr++;
  1110.                             }
  1111.                         }
  1112. #endif
  1113.                     }
  1114. #ifdef CHAR8_OK
  1115.                     else if ( theChar == TAB || (unsigned char)theChar >= SPACE )
  1116. #else
  1117.                     else if ( theChar == TAB ||                theChar >= SPACE )
  1118. #endif
  1119.                     {
  1120.                         chars[0] = theChar;
  1121.                         offset = 1;
  1122.                     }
  1123.                     else {
  1124.                         break;
  1125.                     }
  1126.                     /* Insert character to right of cursor position */
  1127.                     /*  14Aug92  e  for undo...
  1128.                     eTeEdGuts( hE, chars, (long )offset,
  1129.                                  ( chars[0] == RETURN ? TRUE : FALSE ), TRUE, style );
  1130.                     */
  1131.                     eTeKeyIns( hE, chars[0], style );
  1132.                     /* (**hE).maxRight = (**hE).caretRect.right;
  1133.                        -- done in eTeEdGuts --                   02Oct92  e  */
  1134.                     break;
  1135.             } /* END SWITCH ASCII CHARACTER */
  1136.  
  1137.             /* Update selection flag and turn cursor back on */
  1138.             (**hE).selActive = ( PTL( (**hE).selStart ) != PTL( (**hE).selEnd ) );
  1139.             eTeSetCaretState( hE, CARET_ON );
  1140.             HUnlock( (Handle )(**hE).hLines );
  1141.             break;
  1142.     }
  1143. }
  1144.  
  1145. void eTeClick( eRec **hE, Point hitPt, short modifierKeys, long when )
  1146. {
  1147.     ChPos    pos;
  1148.     Point    newPt;
  1149.     Boolean didScroll = TRUE;
  1150.     long    low, high, offset, start, end, anchorStart, anchorEnd;
  1151.     eRec *pE;
  1152.     
  1153.     HLock( (Handle )hE );
  1154.     pE = *hE;
  1155.  
  1156.     if ( ( hE == gLastViewHit )  &&
  1157.          ( ( when - gLastMouseUp.when ) < GetDblTime() )  &&
  1158.          ( Abs ( gLastMouseDown.where.h - hitPt.h ) < 3 ) &&
  1159.          ( Abs ( gLastMouseDown.where.v - hitPt.v ) < 3 ) )
  1160.         gClicks++;
  1161.     else
  1162.         gClicks = 1;
  1163.     gLastViewHit = hE;
  1164.  
  1165.     eTePrepare( hE );
  1166.  
  1167.     eTeSetCaretState( hE, CARET_OFF );
  1168.  
  1169.     if ( gClicks > 3 )
  1170.         gClicks = 3;
  1171.  
  1172.     if ( modifierKeys & shiftKey ) {
  1173.         gClicks = 1;
  1174.         if ( ! (*pE).selActive ) {
  1175.             (*pE).selStart = (*pE).caretChPos;
  1176.             (*pE).selEnd = (*pE).selStart;
  1177.             (*pE).selActive = TRUE;
  1178.         }
  1179.         start = eTeChPosToOffset( hE, (*pE).selStart );
  1180.         end = eTeChPosToOffset( hE, (*pE).selEnd );
  1181.         /*  24Jul92  e  was...
  1182.         if( modifierKeys & optionKey )
  1183.             anchorStart = anchorEnd = end;
  1184.         else
  1185.             anchorStart = anchorEnd = start;
  1186.         s.b.... */
  1187.         if( eTeChPosToOffset( hE, (*pE).caretChPos ) == start )
  1188.             anchorStart = anchorEnd = (long )( ( modifierKeys & optionKey ) ? start : end );
  1189.         else
  1190.             anchorStart = anchorEnd = (long )( ( modifierKeys & optionKey ) ? end : start );
  1191.         /* since caretChPos is the active end    24Jul92  e  */
  1192.     }
  1193.     else if ( (*pE).selActive ) {
  1194.         eTeHiliteRange( hE, (*pE).selStart, (*pE).selEnd );
  1195.         (*pE).selActive = FALSE;
  1196.     }
  1197.  
  1198.     /*
  1199.      * The DO-WHILE loop monitors the cursor while the mouse button is held down.
  1200.      * The selection is modified with changes in the cursor. NewPt is the new
  1201.      * mouse location, while hitPt contains the last position.
  1202.      */
  1203.     newPt = hitPt;
  1204.     do {
  1205.         if ( didScroll || PTL( newPt ) != PTL( hitPt ) ) {
  1206.             /* first time OR did scroll last loop OR mouse has moved */
  1207.             /* (didScroll == TRUE) causes this to execute first time */
  1208.             switch ( gClicks ) {
  1209.                 case 3:
  1210.                     pos = eTePointToChPos( hE, newPt );
  1211.                     pos.h = 0;
  1212.                     low = eTeChPosToOffset( hE, pos );
  1213.                     if ( pos.v < (*pE).bounds.v - 1 ) {
  1214.                         ++pos.v;
  1215.                         pos.h = 0;
  1216.                     }
  1217.                     else {
  1218.                         pos.h = (*(*pE).hLines)[ pos.v + 1 ] - (*(*pE).hLines)[ pos.v ];
  1219.                     }
  1220.                     high = eTeChPosToOffset( hE, pos );
  1221.                     break;
  1222.  
  1223.                 case 2:
  1224.                     offset = eTeChPosToOffset( hE, eTePointToChPos( hE, newPt ) );
  1225.                     low = WordLimits( *(*pE).hText, offset, TRUE );
  1226.                     high = WordLimits( *(*pE).hText, offset, FALSE );
  1227.                     break;
  1228.  
  1229.                 default:
  1230.                     low = eTeChPosToOffset( hE, eTePointToChPos( hE, newPt ) );
  1231.                     high = low;
  1232.                     break;
  1233.             }
  1234.             /*
  1235.              * Use selActive variable to tell us if this is the first time thru.
  1236.              * If so, then set our anchor points.
  1237.              * Otherwise we just update the selection around the anchors.
  1238.              */
  1239.             if ( ! (*pE).selActive ) {
  1240.                 start = anchorStart = low;
  1241.                 end = anchorEnd = high;
  1242.                 eTeHiliteRange( hE, eTeOffsetToChPos( hE, low ), eTeOffsetToChPos(  can't merge k with n (2&4) */
  1243.         if( k > runVec[kr] ) { runVec[++jr] = j + n; kr++; }    /*  13Oct92  e  */
  1244.         while( kr <= qRuns ) runVec[++jr] = runVec[kr++] + adj;
  1245.     }
  1246.     (**hE).qRuns = jr;
  1247.     /* see if we should shrink the runs vector */
  1248.     if ( jr + MIN_RUNS + MIN_RUNS < (**hE).runsAllocated )
  1249.     {    (**hE).runsAllocated = ( jr / MIN_RUNS + 1 ) * MIN_RUNS;
  1250.         SetHandleSize( (Handle )(**hE).hRuns, (**hE).runsAllocated * sizeof( long ) );
  1251.     }
  1252. }
  1253.  
  1254. /* ******** */
  1255.  
  1256. static short eTeUpdateLineStarts( eRec **hE, short firstLine )
  1257. {
  1258.     char hdlState;
  1259.     short error = noErr;
  1260.     register LineRec     *linePtr;
  1261.     register char        *charPtr, c;
  1262.     register short        numLines;
  1263.     register long        maxLine;    /* 28May92  e */
  1264.     register long        offsLine;    /* 28May92  e */
  1265.     register short        wrap;        /*  5Jul92  e */
  1266.     eRec    *pE;
  1267.     char    *pT;
  1268.  
  1269.     MoveHHi( (Handle )hE );
  1270.     HLock( (Handle )hE );
  1271.     pE = *hE;
  1272.     MoveHHi( (*pE).hText );
  1273.     HLock( (*pE).hText );
  1274.     pT  = *(*pE).hText;
  1275.     HLock( (Handle )(*pE).hLines );
  1276.  
  1277.     linePtr = *(*pE).hLines;
  1278.     numLines = firstLine + 1;
  1279.     
  1280.     maxLine = (firstLine == 0) ? 0 : (*pE).bounds.h;    /* 28May92  e  */
  1281.     wrap = (*pE).wrap;                                    /*  5Jul92  e  */
  1282.  
  1283.     /* Scan entire block of text, start with line firstLine */
  1284.     for ( charPtr = linePtr[ firstLine ] + pT; ( c = *charPtr ) != '\0';  ++charPtr )
  1285.     {    /* Found end of line. Store next line's starting position */
  1286.         if ( c == RETURN
  1287.              || ( --wrap <= 0 && (c = charPtr[1]) != RETURN && c != '\0' ) )
  1288.              /* 10Aug92  e  added RETURN test  |  11Aug92  e  added '\0' test  */
  1289.         {    wrap = (*pE).wrap;                                    /*  5Jul92  e  */
  1290.             offsLine = charPtr - pT + 1;
  1291.             if( ( offsLine - linePtr[firstLine] ) >= maxLine )    /* 10Aug92  e  was > */
  1292.                 maxLine = offsLine - linePtr[firstLine] + 1;    /* 10Aug92  e  +1 */
  1293.             linePtr[ ++firstLine ] = offsLine;
  1294.             /* */
  1295.             ++numLines;
  1296.             /* See if we need to allocate more space for our line starts */
  1297.             if ( numLines >= (*pE).linesAllocated )
  1298.             {    (*pE).linesAllocated += MIN_LINES;
  1299.                 HUnlock( (Handle )(*pE).hLines );
  1300.                 SetHandleSize( (Handle )(*pE).hLines, (*pE).linesAllocated * sizeof( LineRec ) );
  1301.                   asm { move.w D0, error }         /* error = MemError(); */
  1302.                   if( error != noErr )
  1303.                   {    HUnlock( (*pE).hText );
  1304.                       HUnlock( (Handle )hE );
  1305.                       return error;
  1306.                   }
  1307.                 MoveHHi( (Handle )(*pE).hLines );
  1308.                 HLock( (Handle )(*pE).hLines );
  1309.                 linePtr = *(*pE).hLines;
  1310.             }
  1311.         }
  1312.     }
  1313.     /* Last entry contains length of entire text block */
  1314.     offsLine = charPtr - pT;
  1315.     if( ( offsLine - linePtr[firstLine] ) >= maxLine )            /* 10Aug92  e  was > */
  1316.         maxLine = offsLine - linePtr[firstLine] + 1;            /* 10Aug92  e  +1 */
  1317.     linePtr[ firstLine + 1 ] = offsLine;
  1318.  
  1319.     HUnlock( (*pE).hText );
  1320.     HUnlock( (Handle )(*pE).hLines );
  1321.  
  1322.     /* See if we should shrink our line starts block */
  1323.     if ( numLines + MIN_LINES < (*pE).linesAllocated ) {
  1324.         (*pE).linesAllocated = ( numLines / MIN_LINES + 1 ) * MIN_LINES;
  1325.         SetHandleSize( (Handle )(*pE).hLines, (*pE).linesAllocated * sizeof( LineRec ) );
  1326.           asm { move.w D0, error }         /* error = MemError(); */
  1327.     }
  1328.  
  1329.     (*pE).bounds.h = Min( maxLine, 32767 );  /* 28May92  e  */
  1330.     (*pE).bounds.v = numLines;
  1331.     HUnlock( (Handle )hE );
  1332.     eTeAdjustScrollMax( hE );
  1333.     return error;
  1334. }
  1335.  
  1336. static short eTeSetTextGuts( eRec** hE, Handle hT, long numChars )
  1337. {    short error = noErr;
  1338.     if ( (**hE).hText )
  1339.         DisposHandle( (**hE).hText );
  1340.     if ( (*hT)[ numChars -1 ] != 0 ) {
  1341.         numChars += 1;
  1342.         SetHandleSize( hT, numChars );
  1343.           asm { move.w D0, error }         /* error = MemError(); */
  1344.           if( error != noErr ) return error;
  1345.     }
  1346.     (*hT)[ numChars - 1 ] = '\0';
  1347.     (**hE).hText = hT;
  1348.     error = eTeUpdateLineStarts( hE, 0 );
  1349.       if( error != noErr ) return error;
  1350.     error = eTeNewRuns( hE, numChars - 1 );
  1351.       if( error != noErr ) return error;
  1352.     (**hE).caretChPos.h = (**hE).caretChPos.v = 0L;
  1353.     (**hE).selStart = (**hE).selEnd = (**hE).caretChPos;
  1354.     (**hE).maxRight = 0;
  1355.     eTeUpdateCaretRect( hE );
  1356.     (**hE).dirty = FALSE;
  1357.     eTeRefresh( hE );                            /* 17Dec92  e  */
  1358.     return error;
  1359. }
  1360.  
  1361.  
  1362. short eTeSetTextHandleDetabify( eRec **hE, Handle hT, short tabstops )
  1363. {    long count;
  1364.     long size = GetHandleSize( hT );
  1365.     short error = DeTabifyHandle( hT, &size, &count, tabstops >= 0 ? tabstops : (**hE).tabStops );
  1366.     if ( error != noErr ) return error;
  1367.     /* see if count lines fit in lineStarts array */
  1368.     if( count > ( 32767 - ( MIN_LINES >> 1) ) )
  1369.         return -357;
  1370.     if ( count >= (**hE).linesAllocated )
  1371.     {    (**hE).linesAllocated = count + ( MIN_LINES >> 1);
  1372.         SetHandleSize( (Handle )(**hE).hLines, (**hE).linesAllocated * sizeof( LineRec ) );
  1373.           asm { move.w D0, error }         /* error = MemError(); */
  1374.           if( error != noErr )
  1375.           {    (**hE).linesAllocated = 0;
  1376.               return error;
  1377.           }
  1378.     }
  1379.     return eTeSetTextGuts( hE, hT, size );
  1380. }
  1381.  
  1382. short eTeSetTextHandle( eRec** hE, Handle hT )
  1383. {
  1384.     return eTeSetTextGuts( hE, hT, GetHandleSize( hT ) );
  1385. }
  1386.  
  1387. short eTeSetTextPtr( eRec** hE, Ptr pT, long numChars )
  1388. {
  1389.     Handle hT;
  1390.     
  1391.     if ( pT[ numChars -1 ] != 0 )
  1392.         numChars += 1;
  1393.     PtrToHand( pT, &hT, numChars );
  1394.     (*hT)[ numChars - 1 ] = '\0';
  1395.     return eTeSetTextGuts( hE, hT, numChars );
  1396. }
  1397.  
  1398. void eTeSetSelect( eRec **hE, long aStart, long anEnd )
  1399. {
  1400.     ChPos    first, last;
  1401.     /* Unhilite existing selection */
  1402.     if ( (**hE).selActive ) {
  1403.         first = (**hE).selStart;
  1404.         last = (**hE).selEnd;
  1405.         eTeHiliteRange( hE, first, last );
  1406.         (**hE).selActive = FALSE;
  1407.     }
  1408.     else
  1409.         eTeSetCaretState( hE, CARET_OFF );
  1410.  
  1411.     if ( aStart < 0 ) aStart = 0;
  1412.     if ( anEnd < 0 ) anEnd = 0;
  1413.     if ( aStart >= anEnd ) {
  1414.         (**hE).selStart = (**hE).selEnd = eTeOffsetToChPos( hE, aStart );
  1415.     }
  1416.     else {
  1417.         (**hE).selActive = TRUE;
  1418.         first = eTeOffsetToChPos( hE, aStart );
  1419.         last = eTeOffsetToChPos( hE, anEnd );
  1420.         (**hE).selStart = first;
  1421.         (**hE).selEnd = last;
  1422.         eTeHiliteRange( hE, first, last );
  1423.     }
  1424.     (**hE).caretChPos = (**hE).selEnd;
  1425.     eTeUpdateCaretRect( hE );
  1426.     (**hE).maxRight = (**hE).caretRect.right;
  1427. }
  1428.  
  1429. static Boolean eTeHasReturns( register char *data, register long len )
  1430. {
  1431.     while( len-- )
  1432.         if ( *data++ == RETURN )
  1433.             return TRUE;
  1434.     return FALSE;
  1435. }
  1436.  
  1437. /* the scrap  13Aug92  e  */
  1438.  
  1439. void     eTePutScrap()
  1440. {    OSErr        err;
  1441.  
  1442.     HLock( eTeScrap );
  1443.     /* Make a copy of the scrap and give to the clipboard */
  1444.     if( ( err = ZeroScrap() ) == noErr )
  1445.     {    err = PutScrap( eTeScrapLen, 'TEXT', *eTeScrap );
  1446.     }
  1447.     if( err == noErr )
  1448.     {    
  1449.     }
  1450.     else SysBeep( 3 );
  1451.     eTeScrapCnt = (InfoScrap())->scrapCount;
  1452.     HUnlock( eTeScrap );
  1453. }
  1454.  
  1455. static void puntUndoStuff()
  1456. {
  1457.     eTeUndoStuff.undoTeRec = NULL;
  1458.     eTeUndoStuff.undoTitle = utUndo;
  1459.     eTeUndoStuff.undoProc  = undoBugNi;
  1460. }
  1461.  
  1462. void     eTeGetScrap()
  1463. {    long offset, length;
  1464.  
  1465.     if( eTeScrapCnt != (InfoScrap())->scrapCount )
  1466.     {    length = GetScrap( NULL, 'TEXT', &offset );
  1467.         if ( length >= 0 )
  1468.         { eTeScrapLen = GetScrap( eTeScrap, 'TEXT', &offset );
  1469.           puntUndoStuff();
  1470.         }
  1471.         else if( length != noTypeErr )
  1472.         { SysBeep( 3 );
  1473.           SetHandleSize( eTeScrap, 0 );
  1474.           eTeScrapLen = 0;
  1475.           puntUndoStuff();
  1476.         }
  1477.         /* else punt: noTypeErr => nothing to copy */
  1478.     }
  1479. }
  1480.  
  1481. /* I don't feel bad using a large buffer on the stack,
  1482.    even on a MacPlus Quickdraw uses several K of stack space to draw text! */
  1483. #define TR_BUF_SZ 4000
  1484.  
  1485. /* ####################################################################
  1486.  
  1487. 14Aug92  e
  1488.  
  1489. Undo notes...
  1490.  
  1491. try to alloc a temp handle in dodoTyping()
  1492.  
  1493. concatenate successive kills (use clip or undo ?) ?
  1494.  
  1495. add to eTeKeyIns() mechanism for delete and del>
  1496.  
  1497.   if undoTyping or undoClear already active && there's no selection
  1498.  
  1499.     if normal char
  1500.       if caret >= undoStart && caret <= undoStart + insertLen
  1501.       increment insertLen
  1502.       insert char
  1503.     else
  1504.       start new undo & keyAccum
  1505.  
  1506.     if Delete
  1507.       if caret > undoStart && caret <= undoStart + insertLen
  1508.         decr insertLen
  1509.         do the delete
  1510.       else if caret == undoStart
  1511.         put character at caret-1 onto front of undoText
  1512.         do the delete
  1513.       else
  1514.         start new undo & keyAccum
  1515.  
  1516.     if Del>
  1517.       if caret >= undoStart && caret < undoStart + insertLen
  1518.         decr insertLen
  1519.         do the delete
  1520.       else if caret == undoStart + insertLen
  1521.         put character at caret onto end of undoText
  1522.         do the delete
  1523.       else
  1524.         start new undo & keyAccum
  1525.  
  1526.   else
  1527.     what's done now
  1528.  
  1529. ensureSelOK() is only necessary
  1530.  because caretChPos is not kept syncronized with selStart & selEnd and vice versa
  1531.  should this be fixed so ensureSelOK() can be eliminated?  for other reasons?
  1532.  
  1533. make eTeTranspose() work better with undo -- at least adjust offsets?
  1534.  
  1535. subroutinize undo routines
  1536.   -- eTeEdGuts( hE, EMPTY_PTR, 0L, FALSE, TRUE, 0 ); ??
  1537.   -- hoseUndoText();
  1538.   -- rsSelectionPts();
  1539.  
  1540. /* ##################### */
  1541.  
  1542. static void ensureSelOK( eRec **hE )                /* can this be eliminated !? */
  1543. {    if( ! (**hE).selActive )
  1544.         (**hE).selStart = (**hE).selEnd = (**hE).caretChPos;
  1545. }
  1546.  
  1547. void eTeUndo( eRec **hE )
  1548. {
  1549.     if( hE == eTeUndoStuff.undoTeRec )
  1550.         eTeUndoStuff.undoProc( hE );
  1551.     else SysBeep( 3 );
  1552. }
  1553.  
  1554. void eTeEditMenuUpdate( eRec **hE, MenuHandle hM )
  1555. {
  1556.     SetItem( hM, 1, eTeUndoStuff.undoTitle );        /* memoize this ?! */
  1557.     if( hE != NULL )
  1558.     {    if( (**hE).selActive )
  1559.         {    EnableItem( hM, 3 ); /* cut */
  1560.             EnableItem( hM, 4 ); /* copy */
  1561.         }
  1562.         else
  1563.         {    DisableItem( hM, 3 ); /* cut */
  1564.             DisableItem( hM, 4 ); /* copy */
  1565.         }
  1566.         EnableItem( hM, 5 ); /* paste */
  1567.         EnableItem( hM, 6 ); /* clear */
  1568.         if( hE == eTeUndoStuff.undoTeRec )
  1569.             EnableItem( hM, 1 );
  1570.         else
  1571.             DisableItem( hM, 1 ); /* undo */
  1572.     }
  1573.     else
  1574.     {    EnableItem( hM, 3 ); /* cut */
  1575.         EnableItem( hM, 4 ); /* copy */
  1576.         EnableItem( hM, 5 ); /* paste */
  1577.         EnableItem( hM, 6 ); /* clear */
  1578.         DisableItem( hM, 1 ); /* undo */
  1579.     }
  1580. }
  1581.  
  1582. static void ssSelectionPts( eRec **hE )
  1583. {    ensureSelOK( hE );
  1584.     eTeUndoStuff.undoInLen = 0;
  1585.     eTeUndoStuff.undoKeyAccum = FALSE;
  1586.     eTeUndoStuff.undoStart = eTeChPosToOffset( hE, (**hE).selStart );
  1587.     eTeUndoStuff.undoEnd   = eTeChPosToOffset( hE, (**hE).selEnd   );
  1588.     eTeUndoStuff.undoCarStaP = PTL( (**hE).caretChPos ) == PTL( (**hE).selStart );
  1589.     eTeUndoStuff.undoDirty = (**hE).dirty;
  1590.     eTeUndoStuff.undoTeRec = hE;
  1591. }
  1592.  
  1593. static void ssSwapScrap()
  1594. {    Handle h;
  1595.     long l;
  1596.     h = eTeScrap;
  1597.     l = eTeScrapLen;
  1598.     eTeScrap = eTeUndoStuff.undoText;
  1599.     eTeScrapLen = eTeUndoStuff.undoTxLen;
  1600.     eTeUndoStuff.undoText = h;
  1601.     eTeUndoStuff.undoTxLen = l;
  1602. }
  1603.  
  1604. static void eTeSetSelCar( eRec **hE, long aStart, long anEnd, Boolean stap )
  1605. {
  1606.     eTeSetSelect( hE, aStart, anEnd );
  1607.     if( stap ) (**hE).caretChPos = (**hE).selStart;
  1608. }
  1609.  
  1610. static void eTePasteNu( eRec **hE, short style )
  1611. {
  1612.     MoveHHi( eTeScrap );
  1613.     HLock( eTeScrap );
  1614.     eTeEdGuts( hE, *eTeScrap, eTeScrapLen, eTeHasReturns( *eTeScrap, eTeScrapLen ), TRUE, style );
  1615.     HUnlock( eTeScrap );
  1616. }
  1617.  
  1618. static void eTeCopyNu( eRec **hE )
  1619. {
  1620.     long        length, offset;
  1621.  
  1622.     /* Get starting position and length of text to copy */
  1623.     offset = eTeChPosToOffset( hE, (**hE).selStart );
  1624.     length = eTeChPosToOffset( hE, (**hE).selEnd ) - offset;
  1625.     MoveHHi( (**hE).hText );
  1626.     HLock( (**hE).hText );
  1627.     /* Make a copy of the text and put in scrap */
  1628.     offset = Munger( eTeScrap, 0L, NULL, eTeScrapLen, *(**hE).hText + offset, length );
  1629.     if( offset == length )
  1630.         eTeScrapLen = length; /* success */
  1631.     else SysBeep( 3 );
  1632.     HUnlock( (**hE).hText );
  1633. }
  1634.  
  1635. static void undoCut( eRec  **hE )                /* Undo Cut */
  1636. {                                                /* restore selection from scrap */
  1637.     eTeSetSelect( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoStart );
  1638.     eTePasteNu( hE, 0 );
  1639.     ssSwapScrap();                                 /* restore scrap */
  1640.     SetHandleSize( eTeUndoStuff.undoText, 0 );
  1641.     eTeUndoStuff.undoTxLen = 0;
  1642.     eTeSetSelCar( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoEnd, eTeUndoStuff.undoCarStaP );
  1643.     (**hE).dirty = eTeUndoStuff.undoDirty;        /* restore selection points & flags */
  1644.     eTeUndoStuff.undoTitle = rtCut;
  1645.     eTeUndoStuff.undoProc  = eTeCut;
  1646. }
  1647.   
  1648. void eTeCut( eRec **hE )                        /*  Cut == RedoCut  */
  1649. {    if( ! (**hE).selActive ) return;
  1650.     ssSelectionPts( hE );  /* snapshot selection points */
  1651.     ssSwapScrap();         /* snapshot scrap */
  1652.     eTeUndoStuff.undoTitle = utCut;
  1653.     eTeUndoStuff.undoProc  = undoCut;
  1654.     eTeCopyNu( hE );                            /* do cut */
  1655.     eTeEdGuts( hE, EMPTY_PTR, 0L, FALSE, TRUE, 0 );
  1656. }
  1657.  
  1658. static void undoCopy( eRec  **hE )                /* Undo Copy */
  1659. {    
  1660.     ssSwapScrap();                                 /* restore scrap */
  1661.     SetHandleSize( eTeUndoStuff.undoText, 0 );
  1662.     eTeUndoStuff.undoTxLen = 0;
  1663.     eTeSetSelCar( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoEnd, eTeUndoStuff.undoCarStaP );
  1664.     (**hE).dirty = eTeUndoStuff.undoDirty;        /* restore selection points & flags */
  1665.     eTeUndoStuff.undoTitle = rtCopy;
  1666.     eTeUndoStuff.undoProc  = eTeCopy;
  1667. }
  1668.   
  1669. void eTeCopy( eRec **hE )                        /* Copy == Redo Copy */
  1670. {    if( ! (**hE).selActive ) return;
  1671.     ssSelectionPts( hE );                          /* snapshot selection points */
  1672.     ssSwapScrap();                                 /* snapshot scrap */
  1673.     eTeUndoStuff.undoTitle = utCopy;
  1674.     eTeUndoStuff.undoProc  = undoCopy;
  1675.     eTeCopyNu( hE );                            /* do copy */
  1676. }
  1677.  
  1678. static void redoPaste( eRec  **hE )                /* Redo Paste */
  1679. {    eTePaste( hE, 0 );
  1680. }
  1681.  
  1682. static void undoPaste( eRec  **hE )                /* Undo Paste */
  1683. {                                                /* restore selection from scrap */
  1684.     eTeSetSelect( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoStart + eTeScrapLen );
  1685.     ssSwapScrap();                                 /* swap scrap & undo */
  1686.     eTePasteNu( hE, 0 );                        /* restore text from undo */
  1687.     ssSwapScrap();                                 /* swap scrap & undo */
  1688.     SetHandleSize( eTeUndoStuff.undoText, 0 );
  1689.     eTeUndoStuff.undoTxLen = 0;
  1690.     eTeSetSelCar( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoEnd, eTeUndoStuff.undoCarStaP );
  1691.     (**hE).dirty = eTeUndoStuff.undoDirty;        /* restore selection points & flags */
  1692.     eTeUndoStuff.undoTitle = rtPaste;
  1693.     eTeUndoStuff.undoProc  = redoPaste;
  1694. }
  1695.  
  1696. void eTePaste( eRec **hE, short style )            /* Paste != Redo Paste */
  1697. {    ssSelectionPts( hE );                          /* snapshot selection points */
  1698.     ssSwapScrap();                                 /* snapshot selection */
  1699.     eTeCopyNu( hE );
  1700.     ssSwapScrap();                                 /* restore scrap */
  1701.     eTeUndoStuff.undoTitle = utPaste;
  1702.     eTeUndoStuff.undoProc  = undoPaste;
  1703.     eTePasteNu( hE, style );                    /* do paste [14Sep92  e  -- added style back] */
  1704. }
  1705.  
  1706. static void undoDelete( eRec **hE )                /* Undo Clear */
  1707. {                                                /* restore selection from scrap */
  1708.     eTeSetSelect( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoStart );
  1709.     ssSwapScrap();                                 /* swap scrap & undo */
  1710.     eTePasteNu( hE, 0 );                        /* restore text from undo */
  1711.     ssSwapScrap();                                 /* swap scrap & undo */
  1712.     SetHandleSize( eTeUndoStuff.undoText, 0 );
  1713.     eTeUndoStuff.undoTxLen = 0;
  1714.     eTeSetSelCar( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoEnd, eTeUndoStuff.undoCarStaP );
  1715.     (**hE).dirty = eTeUndoStuff.undoDirty;        /* restore selection points & flags */
  1716.     eTeUndoStuff.undoTitle = rtClear;
  1717.     eTeUndoStuff.undoProc  = eTeDelete;
  1718. }
  1719.  
  1720. void eTeDelete( eRec **hE )                        /* Clear == Redo Clear */
  1721. {    long offset;
  1722.     if ( ! (**hE).selActive )
  1723.     {    /* Just delete previous character */
  1724.         offset = eTeChPosToOffset( hE, (**hE).caretChPos );
  1725.         if ( offset <= 0 ) return;
  1726.         ssSelectionPts( hE );                          /* snapshot selection points */
  1727.         eTeUndoStuff.undoStart--;
  1728.         (**hE).selEnd = (**hE).caretChPos;
  1729.         (**hE).selStart = eTeOffsetToChPos( hE, --offset );
  1730.     }
  1731.     else
  1732.         ssSelectionPts( hE );                          /* snapshot selection points */
  1733.     ssSwapScrap();                                 /* snapshot selection */
  1734.     eTeCopyNu( hE );
  1735.     ssSwapScrap();                                 /* restore scrap */
  1736.     eTeUndoStuff.undoTitle = utClear;
  1737.     eTeUndoStuff.undoProc  = undoDelete;
  1738.     if ( (**hE).selActive )
  1739.         eTeEdGuts( hE, EMPTY_PTR, 0L, FALSE, TRUE, 0 );
  1740.     else
  1741.     {    (**hE).selEnd = (**hE).caretChPos = (**hE).selStart;
  1742.         eTeSetCaretState( hE, CARET_OFF ); /* 23Jul92  e */
  1743.         eTeUpdateCaretRect( hE );
  1744.         eTeEdGuts( hE, EMPTY_PTR, -1L, *(*(**hE).hText + offset) == RETURN, TRUE, 0 );
  1745.     }
  1746. }
  1747.  
  1748. static void redoKill( eRec **hE )                /* Redo Kill */
  1749. {
  1750.     eTeSetSelect( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoStart );
  1751.     eTeKillTo( hE, eTeOffsetToChPos( hE, eTeUndoStuff.undoEnd ) );
  1752. }
  1753.  
  1754. static void undoKill( eRec  **hE )                /* Undo Kill */
  1755. {                                                /* restore selection from scrap */
  1756.     eTeSetSelect( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoStart );
  1757.     eTePasteNu( hE, 0 );
  1758.     ssSwapScrap();                                 /* restore scrap */
  1759.     SetHandleSize( eTeUndoStuff.undoText, 0 );
  1760.     eTeUndoStuff.undoTxLen = 0;
  1761.     eTeSetSelect( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoStart );
  1762.     (**hE).dirty = eTeUndoStuff.undoDirty;        /* restore selection points & flags */
  1763.     eTeUndoStuff.undoTitle = rtKill;
  1764.     eTeUndoStuff.undoProc  = redoKill;
  1765. }
  1766.   
  1767. void eTeKillTo( eRec **hE, ChPos chPos )        /* Kill != Redo Kill */
  1768. {
  1769.     if( PTL( chPos ) == PTL( (**hE).caretChPos ) ) return;
  1770.     (**hE).selStart = (**hE).caretChPos;        /* mung selection points first! */
  1771.     (**hE).selEnd = chPos;
  1772.     (**hE).selActive = TRUE;
  1773.     ssSelectionPts( hE );                          /* snapshot selection points */
  1774.     ssSwapScrap();                                 /* snapshot scrap */
  1775.     eTeCopyNu( hE );
  1776.     eTeUndoStuff.undoTitle = utKill;
  1777.     eTeUndoStuff.undoProc  = undoKill;
  1778.     /* since we'll redraw the line anyway, eTeHiliteRange isn't necessary!?    */
  1779.     /*  unfortunately, for wrapped lines, it is - otherwise cursor turds; ugh. */
  1780.     /* eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );                   */
  1781.     /* instead we'll fake it out by making the window look inactive instead    */
  1782.     (**hE).active = FALSE;
  1783.     eTeEdGuts( hE, EMPTY_PTR, 0L, FALSE, TRUE, 0 );
  1784.     (**hE).active = TRUE;
  1785. }
  1786.  
  1787. static Boolean dodoTyping( eRec **hE )
  1788. {    char buf[TR_BUF_SZ];
  1789.     long sz;
  1790.     register char *p, *q;
  1791.     register long iter = sz = eTeUndoStuff.undoTxLen;;
  1792.     
  1793.     if( iter > 0 || eTeUndoStuff.undoInLen > 0 )
  1794.     {
  1795.         if( eTeUndoStuff.undoInLen > TR_BUF_SZ )
  1796.         {    SysBeep( 6 );                            /* try to alloc a temp handle ? */
  1797.             return FALSE;
  1798.         }
  1799.         q = buf;
  1800.         p = *eTeUndoStuff.undoText;
  1801.         while( iter-- ) *q++ = *p++;
  1802.         eTeSetSelect( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoStart + eTeUndoStuff.undoInLen );
  1803.         ssSwapScrap();                                 /* snapshot insertion */
  1804.         eTeCopyNu( hE );
  1805.         ssSwapScrap();                                 /* restore scrap */
  1806.         eTeEdGuts( hE, buf, sz, eTeHasReturns( buf, sz ), TRUE, 0 );
  1807.         eTeUndoStuff.undoInLen = sz;
  1808.     }
  1809.     return TRUE;
  1810. }
  1811.  
  1812. static void redoTyping( eRec **hE );
  1813.  
  1814. static void undoTyping( eRec **hE )
  1815. {    if( dodoTyping( hE ) )
  1816.     {    eTeUndoStuff.undoKeyAccum = FALSE;
  1817.         eTeSetSelCar( hE, eTeUndoStuff.undoStart, eTeUndoStuff.undoEnd, eTeUndoStuff.undoCarStaP );
  1818.         (**hE).dirty = eTeUndoStuff.undoDirty;        /* restore selection points & flags */
  1819.         eTeUndoStuff.undoTitle = rtTyping;
  1820.         eTeUndoStuff.undoProc  = redoTyping;
  1821.     }
  1822. }
  1823.     
  1824. static void redoTyping( eRec **hE )
  1825. {    eTeUndoStuff.undoKeyAccum = TRUE;
  1826.     eTeUndoStuff.undoDirty = (**hE).dirty;
  1827.     if( dodoTyping( hE ) )
  1828.     {    eTeUndoStuff.undoTitle = utTyping;
  1829.         eTeUndoStuff.undoProc  = undoTyping;
  1830.     }
  1831.     else
  1832.     {    eTeUndoStuff.undoKeyAccum = FALSE;
  1833.     }
  1834. }
  1835.  
  1836. static void eTeKeyIns( eRec **hE, char c, short style )
  1837. {
  1838.     if( eTeUndoStuff.undoKeyAccum
  1839.         && hE == eTeUndoStuff.undoTeRec
  1840.         && (**hE).selActive == FALSE
  1841.         && eTeChPosToOffset( hE, (**hE).caretChPos )
  1842.              == eTeUndoStuff.undoStart + eTeUndoStuff.undoInLen
  1843.       )
  1844.     {    eTeUndoStuff.undoInLen += 1;            /* incr numChars inserted */
  1845.     }
  1846.     else
  1847.     {    ssSelectionPts( hE );                      /* snapshot selection points */
  1848.         eTeUndoStuff.undoKeyAccum = TRUE;
  1849.         ssSwapScrap();                             /* snapshot selection */
  1850.         eTeCopyNu( hE );
  1851.         ssSwapScrap();                             /* restore scrap */
  1852.         eTeUndoStuff.undoInLen = 1;                /* remember numChars inserted */
  1853.         eTeUndoStuff.undoTitle = utTyping;
  1854.         eTeUndoStuff.undoProc  = undoTyping;
  1855.     }
  1856.     eTeEdGuts( hE, &c, 1, c == RETURN, TRUE, style );
  1857. }
  1858.  
  1859. void eTeInsert( eRec **hE, Ptr textPtr, long numChars, short style )
  1860. {    if( numChars <= 0 ) { eTeDelete( hE ); return; } /* 08Jan93  e  */
  1861.     ssSelectionPts( hE );                          /* snapshot selection points */
  1862.     eTeUndoStuff.undoKeyAccum = TRUE;
  1863.     ssSwapScrap();                                 /* snapshot selection */
  1864.     eTeCopyNu( hE );
  1865.     ssSwapScrap();                                 /* restore scrap */
  1866.     eTeUndoStuff.undoInLen = numChars;            /* remember numChars inserted */
  1867.     eTeUndoStuff.undoTitle = utInsert;
  1868.     eTeUndoStuff.undoProc  = undoTyping;
  1869.     eTeEdGuts( hE, textPtr, numChars, eTeHasReturns( textPtr, numChars ), TRUE, style );
  1870. }
  1871.  
  1872. /* #################################################################### */
  1873.  
  1874. /* eTeTranspose  22Jul92  e  */
  1875.  
  1876. static void eTeTransposeGuts1( eRec **hE, long beg, long mid, long end )
  1877. { char buf[TR_BUF_SZ];
  1878.   long shift = mid - beg;
  1879.   register char *p, *q;
  1880.   register long incr, iter;
  1881.   
  1882.   while( shift > 0 )
  1883.   { incr = Min( shift, TR_BUF_SZ );
  1884.     shift -= incr;
  1885.     /* */
  1886.     p = *(**hE).hText + beg;
  1887.     q = buf;
  1888.     iter = incr;
  1889.     while( iter-- ) *q++ = *p++;
  1890.     /* */
  1891.     p = *(**hE).hText + beg + incr;
  1892.     q = *(**hE).hText + beg;
  1893.     iter = end - beg - incr;
  1894.     while( iter-- ) *q++ = *p++;
  1895.     /* */
  1896.     p = buf;
  1897.     q = *(**hE).hText + end - incr;
  1898.     iter = incr;
  1899.     while( iter-- ) *q++ = *p++;
  1900.   }
  1901. }
  1902.  
  1903. static void eTeTransposeGuts0( eRec **hE, long beg, long midl, long midr, long end )
  1904. { char buf[TR_BUF_SZ];
  1905.   register char *p, *q;
  1906.   register long iter;
  1907.   
  1908.   q = buf;
  1909.   p = *(**hE).hText + midl;
  1910.   iter = midr - midl;
  1911.   while( iter-- ) *q++ = *p++;
  1912.   p = *(**hE).hText + beg;
  1913.   iter = midl - beg;
  1914.   while( iter-- ) *q++ = *p++;
  1915.   q = *(**hE).hText + beg;
  1916.   p = *(**hE).hText + midr;
  1917.   iter = end - midr;
  1918.   while( iter-- ) *q++ = *p++;
  1919.   p = buf;
  1920.   iter = midr - beg;
  1921.   while( iter-- ) *q++ = *p++;
  1922. }
  1923.  
  1924. static void eTeTransposeGuts2( eRec **hE, long beg, long midl, long midr, long end )
  1925.   if( midr - beg <= TR_BUF_SZ )
  1926.   { eTeTransposeGuts0( hE, beg, midl, midr, end );
  1927.   }
  1928.   else
  1929.   { eTeTransposeGuts1( hE, beg, midl, midr );
  1930.     eTeTransposeGuts1( hE, beg, midr, end );
  1931.   }
  1932. }
  1933.  
  1934. void eTeTranspose( eRec **hE, long beg, long midl, long midr, long end )
  1935. { long offs = beg + end - midr;
  1936.   long numChars = end - beg;
  1937.   char *textPtr;
  1938.   
  1939.   if ( (**hE).selActive
  1940.         || beg  <  0
  1941.         || beg  >= midl
  1942.         || midl >  midr
  1943.         || midr >= end
  1944.         || end  >  eTeTextLength( hE ) )
  1945.  { SysBeep(3);
  1946.    return;
  1947.   }
  1948.   eTeSetCaretState( hE, CARET_OFF );
  1949.   if( midl == midr )
  1950.     eTeTransposeGuts1( hE, beg, midr, end );
  1951.   else
  1952.     eTeTransposeGuts2( hE, beg, midl, midr, end );
  1953.   (**hE).selStart = eTeOffsetToChPos( hE, beg );
  1954.   (**hE).selEnd   = eTeOffsetToChPos( hE, end );
  1955.   (**hE).selActive = TRUE;
  1956.   textPtr = *(**hE).hText + beg;
  1957.   /* fake it out by making the window look inactive */
  1958.   (**hE).active = FALSE;
  1959.   eTeEdGuts( hE, textPtr, numChars, eTeHasReturns( textPtr, numChars ), FALSE, 0 );
  1960.   (**hE).active = TRUE;
  1961.   eTeSetSelect( hE, offs, offs );
  1962.   eTeShowCaret( hE );
  1963.   puntUndoStuff();                 /* all bets off for now    --  17Aug92  e */
  1964. }
  1965.  
  1966. /* eTeWrite  9Jul92  e  */
  1967.  
  1968. void eTeWrite( eRec **hE, Ptr textPtr, long numChars, short style )
  1969. {    /* save selection, etc. */
  1970.     long sta = eTeChPosToOffset( hE, (**hE).selStart );
  1971.     long end = eTeChPosToOffset( hE, (**hE).selEnd );
  1972.     long car = eTeChPosToOffset( hE, (**hE).caretChPos );
  1973.     long pos = eTeChPosToOffset( hE, (**hE).writeChPos );
  1974.     short mxr = (**hE).maxRight;                            /* 10Aug92  e  */
  1975.     Boolean mxrp = mxr != (**hE).caretRect.right;            /* 10Aug92  e  */
  1976.     Boolean selp = (**hE).selActive;
  1977.     Boolean stap = selp && car == sta;
  1978.     if( selp ) eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );
  1979.     else       eTeSetCaretState( hE, CARET_OFF );           /*  14Jul92  e  */
  1980.     /* swap caretChPos & writeChPos */
  1981.     (**hE).selActive = FALSE;
  1982.     (**hE).caretChPos = (**hE).writeChPos;
  1983.     eTeUpdateCaretRect( hE );
  1984.     /* show was always FALSE; changed to ( pos == car )     --  14Jul92  e  */
  1985.     eTeEdGuts( hE, textPtr, numChars, eTeHasReturns( textPtr, numChars ), ( pos == car ), style );
  1986.     /* set writeChPos to caretChPos */
  1987.     (**hE).writeChPos = (**hE).caretChPos;
  1988.     /* restore selection, etc. */
  1989.     if( selp )
  1990.     { if( pos < end )
  1991.       { end += numChars;
  1992.         if( pos <= sta ) sta += numChars;
  1993.       }
  1994.     }
  1995.     else
  1996.     { if( pos <= car ) car += numChars;
  1997.       sta = end = car;
  1998.     }
  1999.     eTeSetSelCar( hE, sta, end, stap );
  2000.     if( mxrp ) (**hE).maxRight = mxr;                        /* 10Aug92  e  */
  2001.     if( hE == eTeUndoStuff.undoTeRec )                        /* 17Aug92  e  */    
  2002.     {    if( pos <= eTeUndoStuff.undoStart )
  2003.         {    eTeUndoStuff.undoEnd   += numChars;
  2004.             eTeUndoStuff.undoStart += numChars;
  2005.         }
  2006.         else if( pos < eTeUndoStuff.undoEnd )
  2007.             puntUndoStuff(); /* all bets off */
  2008.         /* else OK, a write after undo stuff */
  2009.     }
  2010. }
  2011.  
  2012. /* 11Aug92  e   rewritten with eol and sol and new eTeUpdateLineStarts case  */
  2013.  
  2014. static Boolean eTeAdjustLineStarts( eRec **hE, register short start, short amount )
  2015. {
  2016.     register short bot = (**hE).bounds.v;
  2017.     register LineRec *linePtr;
  2018.     register long incr;
  2019.     long llen;
  2020.     long sol, eol;
  2021.     char *pT, c;
  2022.  
  2023.     if ( ( incr = (long )amount ) != 0 ) {
  2024.         /* 28May92  e  was: linePtr = *(**hE).hLines + start + 1; */
  2025.         pT = *(**hE).hText;
  2026.         linePtr = *(**hE).hLines + start;
  2027.         sol = *linePtr++;
  2028.         eol = *linePtr + incr;
  2029.         llen = eol - sol;
  2030.         if( llen > (**hE).bounds.h )
  2031.         { (**hE).bounds.h = Min( llen, ( (**hE).wrap + 1 ) );
  2032.           HLock( (Handle )(**hE).hLines );
  2033.           eTeAdjustScrollMax( hE );
  2034.           HUnlock( (Handle )(**hE).hLines );
  2035.         }
  2036. #ifdef use_old_code
  2037.         /* 12Aug92  e  moved to eTeEdGuts() since it's also applicable when hasReturn is TRUE */
  2038.         if( start > 0
  2039.             && pT[sol-1] != RETURN
  2040.             && ( (c = pT[sol]) == RETURN || c == '\0' ) )
  2041.         { /* this line starts off with a RETURN or NUL and prev line has no RETURN */
  2042.           eTeUpdateLineStarts( hE, start - 1 );
  2043.           return TRUE; /* -1 ? */
  2044.         }
  2045.         else
  2046. #endif
  2047.         if( llen > (**hE).wrap || ( (c = pT[eol-1]) != RETURN && c != '\0' ) )
  2048.         { /* this line is longer than wrap or already doesn't end with a RETURN or NUL */
  2049.           eTeUpdateLineStarts( hE, start );
  2050.           return TRUE; /* +1 ? */
  2051.         }
  2052.         while ( start++ < bot )
  2053.             *linePtr++ += incr;
  2054.     }
  2055.     return FALSE;
  2056. }
  2057.  
  2058. /* eTeEdGuts
  2059.     handles insertion, deletion, and substitution
  2060.     If selection is active, then the text of the selection is deleted, then...
  2061.     If numChars is greater than 0, then the given text is inserted;
  2062.      else if numChars is equal to 0, then no text is inserted;
  2063.      otherwise (numChars is less than 0) AND THIS ONLY WORKS IF NO SELECTION...
  2064.        minus numChars characters to the RIGHT of the caret position are deleted.
  2065. */
  2066.  
  2067. static void eTeEdGuts( eRec **hE, Ptr textPtr, long numChars,
  2068.                              Boolean hasReturn, Boolean show, short style )
  2069. {
  2070.     register long    oldLen, offset;
  2071.     Rect            invalidRect;
  2072.     long newWrite = -1; /* 11Aug92  e   was: 0 */
  2073.     char *pT;            /* 12Aug92  e  */
  2074.  
  2075.     if ( (**hE).selActive ) {
  2076.         eTeHiliteRange( hE, (**hE).selStart, (**hE).selEnd );
  2077.         (**hE).selActive = FALSE;
  2078.         offset = eTeChPosToOffset( hE, (**hE).selStart );
  2079.         oldLen = eTeChPosToOffset( hE, (**hE).selEnd ) - offset;
  2080.         if( numChars < 0 ) numChars = 0;    /*  17Aug92  e   */
  2081.         if( (**hE).selEnd.v != (**hE).selStart.v )
  2082.             hasReturn = TRUE; /* 18May92  e   Oops! */
  2083.         else                  /*  5Jul92  2   Oops! */
  2084.             hasReturn |= eTeHasReturns( *(**hE).hText + offset, oldLen );
  2085.         /* 9Jul92  e */
  2086.         if( PTL( (**hE).writeChPos ) > PTL( (**hE).selStart ) )
  2087.         { if( PTL( (**hE).writeChPos ) < PTL( (**hE).selEnd ) )
  2088.             (**hE).writeChPos = (**hE).selStart;
  2089.           else
  2090.             newWrite = eTeChPosToOffset( hE, (**hE).writeChPos ) + numChars - oldLen;
  2091.         }
  2092.         /* */
  2093.         (**hE).caretChPos = (**hE).selEnd = (**hE).selStart;
  2094.         /* 3May92  e  broken by AppleArrows
  2095.         topLeft( invalidRect ) = eTeChPosToPoint( hE, (**hE).caretChPos );
  2096.         invalidRect.left -= 1;
  2097.         */
  2098.         eTeUpdateCaretRect( hE );
  2099.         topLeft( invalidRect ) = topLeft( (**hE).caretRect );
  2100.     }
  2101.     else {
  2102.         eTeSetCaretState( hE, CARET_OFF ); /* 23Jul92  e */
  2103.         offset = eTeChPosToOffset( hE, (**hE).caretChPos );
  2104.         /*  17Aug92  e  was: oldLen = numChars ? 0 : 1; */
  2105.         if( numChars < 0 )
  2106.         {    oldLen = - numChars;
  2107.             numChars = 0;
  2108.         }
  2109.         else oldLen = 0;
  2110.         /* 9Jul92  e */
  2111.         if( PTL( (**hE).writeChPos ) > PTL( (**hE).caretChPos ) )
  2112.           newWrite = eTeChPosToOffset( hE, (**hE).writeChPos ) + numChars - oldLen;
  2113.         /* */
  2114.         topLeft( invalidRect ) = topLeft( (**hE).caretRect );
  2115.     }
  2116.  
  2117.     /* Do substitution/insertion */
  2118.     Munger( (**hE).hText, offset, NULL, oldLen, textPtr, numChars );
  2119.     (**hE).dirty = TRUE;
  2120.     
  2121.     /* 12Aug92  e    as a result of adding line wrap, need to check if
  2122.                      preceeding line could be 'unwrapped' by this edit...
  2123.     */
  2124.     if( (**hE).caretChPos.h == 0                          /* edit is at the start of a line */
  2125.         && offset > 0                                      /* and it's not the first line */
  2126.         && ((pT=*(**hE).hText))[offset-1] != RETURN       /* and the prev line is a wrapped line */
  2127.         && ( pT[offset] == RETURN || pT[offset] == '\0' ) /* and this line starts with CR or NUL */
  2128.       )
  2129.     {    hasReturn = TRUE;
  2130.         eTeUpdateLineStarts( hE, (**hE).caretChPos.v - 1 );
  2131.         (**hE).caretChPos = eTeOffsetToChPos( hE, offset );
  2132.         eTeUpdateCaretRect( hE );
  2133.         topLeft( invalidRect ) = topLeft( (**hE).caretRect );
  2134.     }
  2135.     else if( hasReturn )
  2136.         eTeUpdateLineStarts( hE, (**hE).caretChPos.v );
  2137.     else
  2138.         hasReturn |= eTeAdjustLineStarts( hE, (**hE).caretChPos.v, numChars - oldLen );
  2139.     
  2140.     eTeUpdateRuns( hE, offset, offset + oldLen, numChars, style );
  2141.  
  2142.     invalidRect.right = (**hE).viewRect.right;        /* 21Jul92  e  moved outside of cond */
  2143.     
  2144.     /* Redraw the current line, starting at the caret */
  2145.     if ( invalidRect.left < (**hE).viewRect.right ) {
  2146.         invalidRect.bottom = invalidRect.top + (**hE).vScale;
  2147.         eTePrepare( hE );
  2148.         ++invalidRect.left;  /* move up here 23Jul92  e  */
  2149.         EraseRect( &invalidRect );
  2150.         /* ++invalidRect.left; !?  22Jul92  e  */
  2151.         eTeDrawLine( hE, (**hE).caretChPos, topLeft( invalidRect ) );
  2152.     }
  2153.  
  2154.     /* if RETURN added, redraw from the next line to the end of the screen */
  2155.     if ( hasReturn ) {
  2156.         invalidRect.top += (**hE).vScale;
  2157.         /* this left ghost on left edge when xor caret used...
  2158.         invalidRect.left = (**hE).leftMargin - (**hE).hOrigin;
  2159.         23Jul92  e  -- instead... */
  2160.         invalidRect.left =  (**hE).viewRect.left;
  2161.         invalidRect.bottom = (**hE).viewRect.bottom;
  2162.         /* eTePrepare( hE );  -- done by eTeDraw  21Jul92  e  */
  2163.         eTeDraw( hE, &invalidRect );
  2164.         (**hE).caretChPos = eTeOffsetToChPos( hE, offset + numChars );
  2165.         eTeUpdateCaretRect( hE );
  2166.     }
  2167.     /* Otherwise, just adjust the caret point by moving it over the inserted text */
  2168.     else {
  2169.          eTePrepare( hE );
  2170.          eTePrepareStyle( hE, style );
  2171.          (**hE).caretChPos.h += numChars;
  2172.         for ( ; numChars > 0 ; ++textPtr, --numChars ) {
  2173.             if ( *textPtr == TAB ) {
  2174.                 (**hE).caretRect.right = eTeTabStop( hE, (**hE).caretRect.right );
  2175.             }
  2176.             else
  2177.                 (**hE).caretRect.right += CharWidth( *textPtr );
  2178.         }
  2179.         (**hE).caretRect.left = (**hE).caretRect.right - 1;
  2180.     }
  2181.     /* 9Jul92  e */
  2182.     if( newWrite >= 0 ) /* 11Aug92  e   was: != 0 */
  2183.       (**hE).writeChPos = eTeOffsetToChPos( hE, newWrite );
  2184.     /* */
  2185.     if( show ) eTeShowCaret( hE );
  2186.     (**hE).maxRight = (**hE).caretRect.right;    /*  02Oct92  e  */
  2187. }
  2188.  
  2189. static short eTeChPosVToPointV( eRec **hE, short v )
  2190. {
  2191.     register long tmp;
  2192.  
  2193.     tmp = (long )v * (**hE).vScale + (**hE).topMargin - (**hE).vOrigin;
  2194.     if( tmp < -32000 )
  2195.         return -32000;
  2196.     if( tmp > 32000 )
  2197.         return 32000;
  2198.     return (short )tmp;
  2199. }
  2200.  
  2201. Point eTeChPosToPoint( eRec **hE, register ChPos aPos )
  2202. {
  2203.     register char *charPtr, c;
  2204.     register short left;
  2205.     long     offset, instyle;
  2206.     short     run;
  2207.     Point    pt;
  2208.  
  2209.     SignedByte hdlState;
  2210.  
  2211.     hdlState = HGetState( (**hE).hText );
  2212.     HLock( (**hE).hText );
  2213.  
  2214.     eTePrepare( hE );
  2215.     offset = *( *(**hE).hLines + aPos.v );
  2216.     charPtr = *(**hE).hText + offset;
  2217.     run = eTeOffsetToRun( hE, offset );
  2218.     left = (**hE).leftMargin - (**hE).hOrigin;
  2219.     do
  2220.     {    eTePrepareRun( hE, run );
  2221.         instyle = (*(**hE).hRuns)[++run] - offset;
  2222.         offset += instyle;
  2223.         while ( instyle-- && aPos.h-- )
  2224.         {    c = *charPtr++;
  2225.             if ( c == TAB )
  2226.                 left = eTeTabStop( hE, left );
  2227.             else
  2228.                 left += CharWidth( c );
  2229.         }
  2230.     } while( aPos.h > 0 );
  2231.  
  2232.     HSetState( (**hE).hText, hdlState );
  2233.  
  2234.     pt.h = left;
  2235.  
  2236.     /* may exceed limits of sixteen bits...
  2237.     pt.v = aPos.v * (**hE).vScale + (**hE).topMargin - (**hE).vOrigin;
  2238.     */
  2239.     pt.v = eTeChPosVToPointV( hE, aPos.v);
  2240.  
  2241.     return( pt );
  2242. }
  2243.  
  2244. static ChPos eTePointHtoChPosH( eRec **hE, register Point aPt, register ChPos aPos )
  2245. {
  2246.     register char *charPtr;
  2247.     register short left, c, limit;
  2248.     SignedByte hdlState;
  2249.     long     offset, instyle;
  2250.     short     run;
  2251.     Point    pt;
  2252.  
  2253.     hdlState = HGetState( (**hE).hText );
  2254.     HLock( (**hE).hText );
  2255.  
  2256.     eTePrepare( hE );
  2257.     /* Stop when we reach the point.h given to us */
  2258.     left = (**hE).leftMargin - (**hE).hOrigin;
  2259.     offset = *( *(**hE).hLines + aPos.v );
  2260.     charPtr = *(**hE).hText + offset;
  2261.     limit = *(*(**hE).hLines + aPos.v + 1) - *(*(**hE).hLines + aPos.v);
  2262.     /* 5Jul92  e  if ( aPos.v < (**hE).bounds.v - 1 ) --limit; */
  2263.     if ( charPtr[limit-1] == RETURN ) --limit;    /* 5Jul92  e   */
  2264.     run = eTeOffsetToRun( hE, offset );
  2265.     aPos.h = 0;
  2266.     do
  2267.     {    eTePrepareRun( hE, run );
  2268.         instyle = (*(**hE).hRuns)[++run] - offset;
  2269.         offset += instyle;
  2270.         while ( instyle-- && ( aPos.h < limit ) )
  2271.         {    c = *charPtr++;
  2272.             if ( c == TAB )
  2273.                 c = eTeTabStop( hE, left );
  2274.             else
  2275.                 c = CharWidth( c ) + left;
  2276.             /* see if we have passed the point */
  2277.             if ( c >= aPt.h )
  2278.             {    /* see if the point is in the second half of the character,
  2279.                    if so the returned value points to the next character. */
  2280.                 if ( c - aPt.h <= aPt.h - left ) aPos.h++;
  2281.                 limit = -1; /* force outer loop escape */
  2282.                 break;
  2283.             }
  2284.             left = c;
  2285.             aPos.h++;
  2286.         }
  2287.     } while( aPos.h < limit );
  2288.  
  2289.     HSetState( (**hE).hText, hdlState );
  2290.     return( aPos );
  2291. }
  2292.  
  2293. ChPos eTePointToChPos( eRec **hE, register Point aPt )
  2294. {
  2295.     register ChPos aPos;
  2296.  
  2297.     /* Restrict point to selectable text */
  2298.     if ( aPt.v < (**hE).topMargin - (**hE).vOrigin ) {
  2299.         aPos.v = 0;
  2300.         aPos.h = 0;
  2301.         return( aPos );
  2302.     }
  2303.     else {
  2304.         aPos.v = ( aPt.v - (**hE).topMargin + (**hE).vOrigin ) / (**hE).vScale;
  2305.         /* Past bottom of text? */
  2306.         if ( aPos.v > (**hE).bounds.v - 1 ) {
  2307.             aPos.v = (**hE).bounds.v - 1;
  2308.             aPos.h = *(*(**hE).hLines + aPos.v + 1) - *(*(**hE).hLines + aPos.v);
  2309.             return( aPos );
  2310.         }
  2311.     }
  2312.     return eTePointHtoChPosH( hE, aPt, aPos );
  2313. }
  2314.  
  2315. ChPos eTeOffsetToChPos( eRec **hE, register long anOffset )
  2316. {
  2317.     register ChPos aPos;
  2318.     register LineRec *linePtr;
  2319.     register long numLines, count, j;
  2320.  
  2321.     if ( anOffset < 0 ) {
  2322.         aPos.h = 0;
  2323.         aPos.v = 0;
  2324.         return( aPos );
  2325.     }
  2326.  
  2327.     linePtr = *(**hE).hLines;
  2328.     count = 0;
  2329.     numLines = (**hE).bounds.v - 1;
  2330. #ifdef use_original_slow_version
  2331.     while ( anOffset >= linePtr[ count + 1 ] && count < numLines )
  2332.         ++count;
  2333.     aPos.v = count;
  2334. #else
  2335.     while ( count < numLines )    {
  2336.         j = (count + numLines - 1) >> 1;
  2337.         if( anOffset < linePtr[ j ] )
  2338.             numLines = j;
  2339.         else if( anOffset >= linePtr[ j + 1 ] )
  2340.             count = j + 1;
  2341.         else    {
  2342.             count = j;
  2343.             break;
  2344.         }
  2345.     }
  2346.     aPos.v = count;
  2347. #endif
  2348.  
  2349.     if ( anOffset > linePtr[ count + 1 ] )
  2350.         aPos.h = linePtr[ count + 1 ] - linePtr[ count ];
  2351.     else
  2352.         aPos.h = anOffset - linePtr[ count ];
  2353.     return( aPos );
  2354. }
  2355.  
  2356. long eTeChPosToOffset( eRec **hE, ChPos aPos )
  2357. {
  2358.     return( *(*(**hE).hLines + aPos.v) + aPos.h );
  2359. }
  2360.  
  2361. void eTeShowCaret( eRec **hE )
  2362. {
  2363.     short        deltaH, deltaV;
  2364.     register eRec *pE = *hE;
  2365.  
  2366.     deltaH = 0;
  2367.     deltaV = 0;
  2368.  
  2369.     /* 30Apr92  e  -- was...
  2370.     if ( (*pE).caretRect.bottom > (*pE).viewRect.bottom )
  2371.         deltaV = ( (*pE).caretRect.bottom - (*pE).viewRect.bottom + (*pE).vScale - 1 ) / (*pE).vScale;
  2372.     else if ( (*pE).caretRect.top < (*pE).viewRect.top ) {
  2373.         deltaV = ( (*pE).caretRect.top - (*pE).viewRect.top ) / (*pE).vScale;
  2374.     */
  2375.     if ( (*pE).caretChPos.v >= (*pE).position.v + (*pE).vSpan )
  2376.         deltaV = (*pE).caretChPos.v - (*pE).position.v - (*pE).vSpan
  2377.                 + Min( (*pE).vContext, (*pE).vSpan >> 1 );
  2378.     else if ( (*pE).caretChPos.v < (*pE).position.v )
  2379.         deltaV = (*pE).caretChPos.v - (*pE).position.v
  2380.                  - Min( Min( (*pE).vContext, (*pE).vSpan >> 1 ), (*pE).caretChPos.v );
  2381.     /* NG for tabs and variable width fonts...
  2382.     if ( (*pE).caretChPos.h >= (*pE).position.h + (*pE).hSpan )
  2383.         deltaH = (*pE).caretChPos.h - (*pE).position.h - (*pE).hSpan + 1;
  2384.     else if ( (*pE).caretChPos.h < (*pE).position.h )
  2385.         deltaH = (*pE).caretChPos.h - (*pE).position.h;
  2386.     */
  2387.     if ( (*pE).caretRect.right > (*pE).viewRect.right )
  2388.         deltaH = ( (*pE).caretRect.right - (*pE).viewRect.right + (*pE).hScale - 1 ) / (*pE).hScale;
  2389.     else if ( (*pE).caretRect.left <= (*pE).viewRect.left ) /* was: (*pE).caretRect.right  22Jul92  e  */
  2390.     {    if( (*pE).caretRect.right + (*pE).hOrigin < (*pE).width )                        /* 22Jul92  e  */
  2391.             deltaH = - (*pE).hOrigin;                                                    /* 22Jul92  e  */
  2392.         else                                                                            /* 22Jul92  e  */
  2393.             deltaH = (*pE).caretRect.right;
  2394.         deltaH = ( deltaH - (*pE).viewRect.left - (*pE).hScale + 1 ) / (*pE).hScale;
  2395.     }
  2396.     if ( deltaH || deltaV )
  2397.     {    eTeScroll( hE, deltaH, deltaV, TRUE );
  2398.         eTeAdjustScrollMax( hE );
  2399.         eTeCalibrate( hE );
  2400.     }
  2401. }
  2402.  
  2403. /* scrolling (Panorama) */
  2404.  
  2405. /* 30Apr92  e  -- eTeScroll rewritten for >32K pixel document height */
  2406.  
  2407. void eTeScroll( eRec **hE, short hDelta, short vDelta, Boolean redraw )
  2408. {
  2409.     long            hPixels;
  2410.     long            vPixels;
  2411.     Rect            tempRect;
  2412.     register eRec    *pE;
  2413.  
  2414.     hPixels = (long )hDelta * (**hE).hScale;
  2415.     vPixels = (long )vDelta * (**hE).vScale;
  2416.     
  2417. #if 0                    /* 25Jan93  e  - to get rid of annoying inappropriate validation */
  2418.     if (redraw) {
  2419.         eTePrepare( hE );
  2420.         tempRect = (**hE).viewRect;
  2421.         if( vPixels < 32767 && vPixels > -32767 )
  2422.         {    ScrollRect( &tempRect, (short )-hPixels, (short )-vPixels, gUtilRgn );
  2423.             InvalRgn( gUtilRgn );
  2424.         }
  2425.         else InvalRect( &tempRect );
  2426.     }
  2427. #else
  2428.     if (redraw)
  2429.     {    eTePrepare( hE );
  2430.         tempRect = (**hE).viewRect;
  2431.         if( vPixels < (**hE).height && vPixels > -(**hE).height )
  2432.         {    if ( ! EmptyRgn( ((WindowPeek)(**hE).macPort)->updateRgn ) )
  2433.             {    BeginUpdate( (**hE).macPort );
  2434.                 eTeUpdate( hE );
  2435.                 EndUpdate( (**hE).macPort );
  2436.             }
  2437.             ScrollRect( &tempRect, (short )-hPixels, (short )-vPixels, gUtilRgn );
  2438.             InvalRgn( gUtilRgn );
  2439.         }
  2440.         else InvalRect( &tempRect );
  2441.     }
  2442. #endif
  2443.  
  2444.     pE = *hE;
  2445.     
  2446.     (*pE).position.h += hDelta;
  2447.     (*pE).position.v += vDelta;
  2448.  
  2449.     (*pE).hOrigin += hPixels;
  2450.     (*pE).vOrigin += vPixels;
  2451.     
  2452.     (*pE).maxRight    -= hPixels;
  2453.     (*pE).caretRect.left -= hPixels;
  2454.     (*pE).caretRect.right -= hPixels;
  2455.     (*pE).caretRect.top = eTeChPosVToPointV( hE, (*pE).caretChPos.v );
  2456.     (*pE).caretRect.bottom = (*pE).caretRect.top + (*pE).caretHeight;
  2457.  
  2458.     if (redraw) {
  2459.         BeginUpdate( (*pE).macPort );
  2460.         eTeUpdate( hE );
  2461.         EndUpdate( (**hE).macPort );
  2462.     }
  2463. }
  2464.  
  2465. void eTeScrollTo( eRec **hE, ChPos aPosition, Boolean redraw )
  2466. {
  2467.     eTeScroll( hE, aPosition.h - (**hE).position.h, aPosition.v - (**hE).position.v, redraw );
  2468.     eTeAdjustScrollMax( hE );
  2469.     eTeCalibrate( hE );
  2470. }
  2471.  
  2472. static Boolean eTeAutoScroll( eRec **hE, Point mouseLoc )
  2473. {
  2474.     short        hDelta = 0;
  2475.     short        vDelta = 0;
  2476.  
  2477.     if ( mouseLoc.h < (**hE).viewRect.left ) {
  2478.         hDelta = Max( -(**hE).hStep, -(**hE).position.h );
  2479.         if (hDelta > 0) {
  2480.             hDelta = 0;
  2481.         }
  2482.     } else if ( mouseLoc.h > (**hE).viewRect.right ) {
  2483.         hDelta = Min( (**hE).hStep, (**hE).bounds.h - (**hE).position.h - (**hE).hSpan );
  2484.         if (hDelta < 0) {
  2485.             hDelta = 0;
  2486.         }
  2487.     }
  2488.     
  2489.     if ( mouseLoc.v < (**hE).viewRect.top ) {
  2490.         vDelta = Max( -(**hE).vStep, -(**hE).position.v );
  2491.         if (vDelta > 0) {
  2492.             vDelta = 0;
  2493.         }
  2494.     } else if ( mouseLoc.v >=
  2495.                     /* (**hE).viewRect.bottom */
  2496.                     (**hE).viewRect.top + (**hE).vSpan * (**hE).vScale
  2497.                      ) {
  2498.         vDelta = Min( (**hE).vStep, (**hE).bounds.v - (**hE).position.v - (**hE).vSpan );
  2499.         if (vDelta < 0) {
  2500.             vDelta = 0;
  2501.         }
  2502.     }
  2503.     
  2504.     if ( (hDelta != 0) || (vDelta != 0) ) {
  2505.         eTeScroll( hE, hDelta, vDelta, TRUE );
  2506.         eTeCalibrate( hE );
  2507.         eTePrepare( hE );
  2508.         return(TRUE);
  2509.     } else {
  2510.         return(FALSE);
  2511.     }
  2512. }
  2513.  
  2514. static void eSbPrepare( eRec **hE )
  2515. {
  2516.     SetPort( (**hE).macPort );
  2517.     ClipRect( &(**hE).macPort->portRect );
  2518. }
  2519.  
  2520. static void eTeAdjustScrollMax( eRec **hE )
  2521. {
  2522.     short            hSpan;
  2523.     short            vSpan;
  2524.     
  2525.     eSbPrepare( hE );
  2526.  
  2527.     (**hE).hSpan = hSpan = (**hE).width / (**hE).hScale;
  2528.     (**hE).vSpan = vSpan = (**hE).height / (**hE).vScale;
  2529.     
  2530.     if ( (**hE).hSBar != NULL ) {
  2531.         SetCtlMax( (**hE).hSBar, Max( ( (**hE).bounds.h - hSpan ), (**hE).position.h ) );
  2532.     }
  2533.  
  2534.     if ( (**hE).vSBar != NULL ) {
  2535.         SetCtlMax( (**hE).vSBar, Max( ( (**hE).bounds.v - vSpan ), (**hE).position.v ) );
  2536.     }
  2537. }
  2538.  
  2539. static void eTeCalibrate( eRec **hE )
  2540. {
  2541.     eSbPrepare( hE );
  2542.  
  2543.     if ( (**hE).hSBar != NULL ) {
  2544.         SetCtlValue( (**hE).hSBar, (**hE).position.h );
  2545.     }
  2546.     if ( (**hE).vSBar != NULL ) {
  2547.         SetCtlValue( (**hE).vSBar, (**hE).position.v );
  2548.     }
  2549. }
  2550.  
  2551. static short countKeys()
  2552. {    KeyMap km;
  2553.     register short count = 1;
  2554.     register short i = 4;
  2555.     register long kmi;
  2556.     
  2557.     GetKeys( km );
  2558.     while( i-- )
  2559.     {    kmi = km[i];
  2560.         while( kmi )
  2561.         {    count <<= 1;
  2562.             kmi &= (kmi-1);
  2563.         }
  2564.     }
  2565.     return count;
  2566. }
  2567.  
  2568. static void eTeDoHscroll( eRec **hE, short whichPart )
  2569. {
  2570.     register short        delta;            /* Number of pixels to scroll        */
  2571.     short                oldValue;        /* Current scroll bar setting        */
  2572.     register short        minmax;            /* Minimum or Maximum delta            */
  2573.     long                ticks;            /* Tick count at end of Delay        */
  2574.  
  2575.     switch (whichPart) {
  2576.         case inUpButton:
  2577.             delta = -( (**hE).hStep * countKeys() );
  2578.             break;
  2579.         case inDownButton:
  2580.             delta =  ( (**hE).hStep * countKeys() );
  2581.             break;
  2582.         case inPageUp:
  2583.             Delay(PAGE_DELAY, &ticks);
  2584.             delta = (**hE).hOverlap - (**hE).hSpan;
  2585.             break;
  2586.         case inPageDown:
  2587.             Delay(PAGE_DELAY, &ticks);
  2588.             delta = (**hE).hSpan - (**hE).hOverlap;
  2589.             break;
  2590.     }
  2591.     oldValue = GetCtlValue( (**hE).hSBar );
  2592.     if (delta < 0) {
  2593.         minmax = GetCtlMin( (**hE).hSBar ) - oldValue;
  2594.         if (delta < minmax)
  2595.             delta = minmax;
  2596.     } else {
  2597.         minmax = GetCtlMax( (**hE).hSBar ) - oldValue;
  2598.         if (delta > minmax)
  2599.             delta = minmax;
  2600.     }
  2601.     if (delta != 0) {
  2602.         eSbPrepare( hE );
  2603.         SetCtlValue( (**hE).hSBar, oldValue + delta );
  2604.         eTeScroll( hE, delta, 0, TRUE );
  2605.         eSbPrepare( hE );
  2606.     }
  2607. }
  2608.     
  2609. static void eTeDoVscroll( eRec **hE, short whichPart )
  2610. {
  2611.     register short        delta;            /* Number of pixels to scroll        */
  2612.     short                oldValue;        /* Current scroll bar setting        */
  2613.     register short        minmax;            /* Minimum or Maximum delta            */
  2614.     long                ticks;            /* Tick count at end of Delay        */
  2615.  
  2616.     switch (whichPart) {
  2617.         case inUpButton:
  2618.             delta = -( (**hE).vStep * countKeys() );
  2619.             break;
  2620.         case inDownButton:
  2621.             delta =  ( (**hE).vStep * countKeys() );
  2622.             break;
  2623.         case inPageUp:
  2624.             Delay(PAGE_DELAY, &ticks);
  2625.             delta = (**hE).vOverlap - (**hE).vSpan;
  2626.             break;
  2627.         case inPageDown:
  2628.             Delay(PAGE_DELAY, &ticks);
  2629.             delta = (**hE).vSpan - (**hE).vOverlap;
  2630.             break;
  2631.     }
  2632.     oldValue = GetCtlValue( (**hE).vSBar );
  2633.     if (delta < 0) {
  2634.         minmax = GetCtlMin( (**hE).vSBar ) - oldValue;
  2635.         if (delta < minmax)
  2636.             delta = minmax;
  2637.     } else {
  2638.         minmax = GetCtlMax( (**hE).vSBar ) - oldValue;
  2639.         if (delta > minmax)
  2640.             delta = minmax;
  2641.     }
  2642.     if (delta != 0) {
  2643.         eSbPrepare( hE );
  2644.         SetCtlValue( (**hE).vSBar, oldValue + delta );
  2645.         eTeScroll( hE, 0, delta, TRUE );
  2646.         eSbPrepare( hE );
  2647.     }
  2648. }
  2649.     
  2650. /* called continuously while mouse down within a fixed part of a scroll bar.
  2651.    Called by the Toolbox during the TrackControl trap. */
  2652.  
  2653. static pascal void hSBarActionProc( ControlHandle macControl, short whichPart )
  2654. {
  2655.     eRec    **hE; 
  2656.     
  2657.     if (whichPart != 0) {
  2658.         hE = (eRec **)GetCRefCon( macControl );
  2659.         eTeDoHscroll( hE, whichPart );
  2660.     }
  2661. }
  2662.  
  2663. static pascal void vSBarActionProc( ControlHandle macControl, short whichPart )
  2664. {
  2665.     eRec    **hE; 
  2666.     
  2667.     if (whichPart != 0) {
  2668.         hE = (eRec **) GetCRefCon( macControl );
  2669.         eTeDoVscroll( hE, whichPart );
  2670.     }
  2671. }
  2672.  
  2673. /* end of os_mac_eEdit.c */